Skip to content

fix: add image/* filter for custom emoji file input#39175

Open
dodaa08 wants to merge 5 commits intoRocketChat:developfrom
dodaa08:fix/FileUploadCustomEmoji
Open

fix: add image/* filter for custom emoji file input#39175
dodaa08 wants to merge 5 commits intoRocketChat:developfrom
dodaa08:fix/FileUploadCustomEmoji

Conversation

@dodaa08
Copy link
Contributor

@dodaa08 dodaa08 commented Feb 27, 2026

Proposed changes (including videos or screenshots)

This fix adds a file type filter when uploading custom emojis so that only image files are selectable, making the upload process faster and more intuitive.

Before

Screen.Recording.2026-02-28.014822.mp4

After

Screen.Recording.2026-02-28.015007.mp4

Steps to test or reproduce

  1. Go to Admin → Emoji.
  2. Click New.
  3. Enter a name and attempt to upload an image.
  4. Before: All files are visible, including non-images.
  5. After: Only image files are selectable.

Further comments

This change improves UX by preventing non-image files from appearing in the upload dialog for custom emojis.

Summary by CodeRabbit

  • New Features
    • File upload inputs can now be configured to accept specific file types (e.g., audio/mp3, .zip) where used.
  • Refactor
    • File upload hook configuration streamlined to support an options-based setup (no behavioral changes for users).
  • Tests
    • Added comprehensive test suite for file upload handling, file-type filtering, callbacks, reset, and cleanup.

@dodaa08 dodaa08 requested a review from a team as a code owner February 27, 2026 20:40
@changeset-bot
Copy link

changeset-bot bot commented Feb 27, 2026

⚠️ No Changeset found

Latest commit: 53941e1

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

@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented Feb 27, 2026

Looks like this PR is not ready to merge, because of the following issues:

  • This PR is missing the 'stat: QA assured' label
  • This PR is missing the required milestone or project

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 27, 2026

Walkthrough

The useSingleFileInput hook API is refactored to accept file type via an options object instead of as a direct parameter, defaulting to 'image/*'. Comprehensive tests are added, and three call sites are updated to use the new signature.

Changes

Cohort / File(s) Summary
Hook API and Tests
apps/meteor/client/hooks/useSingleFileInput.ts, apps/meteor/client/hooks/useSingleFileInput.spec.ts
Hook signature changed to accept options object with optional fileType property instead of direct fileType parameter. Dependency array updated accordingly. New test suite covers input creation, accept attribute handling with defaults, click propagation, and callback invocation with FormData.
Call Site Updates
apps/meteor/client/views/admin/customSounds/AddCustomSound.tsx, apps/meteor/client/views/admin/customSounds/EditSound.tsx, apps/meteor/client/views/marketplace/AppInstallPage.tsx
Updated useSingleFileInput invocations to pass fileType via options object with new parameter order. AddCustomSound and EditSound now pass 'sound' as field identifier with fileType in options. AppInstallPage adds fileType constraint for ZIP files.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title mentions 'custom emoji file input' but the changeset refactors the useSingleFileInput hook itself and updates multiple call sites (custom sounds, app installation, etc.), not just custom emoji functionality. Update title to reflect the broader scope, such as 'refactor: update useSingleFileInput hook to accept options object' or 'refactor: add fileType option to useSingleFileInput hook'.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
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
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 2 files

Copy link
Member

@dougfabris dougfabris left a comment

Choose a reason for hiding this comment

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

The usage of useSingleFileInput has been broken in all places its being used. I think we could refactor it to accept the fileField as second argument and a third argument as an options object with fileType with image/* as default value. Would be great to have some unit tests for this hook as well so we can prevent future issues like the one you aim to fix here.

Are you up to help on this?

@dodaa08
Copy link
Contributor Author

dodaa08 commented Feb 27, 2026

The usage of useSingleFileInput has been broken in all places its being used. I think we could refactor it to accept the fileField as second argument and a third argument as an options object with fileType with image/* as default value. Would be great to have some unit tests for this hook as well so we can prevent future issues like the one you aim to fix here.

Are you up to help on this?

Yeah sure, I am up for fixing them, it's getting a bit late around here, but will push the requested changes by morning. Thanks!

Copy link
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.

1 issue found across 7 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/meteor/client/hooks/useSingleFileInput.spec.ts">

<violation number="1" location="apps/meteor/client/hooks/useSingleFileInput.spec.ts:13">
P2: Test creates its own input element instead of asserting the hook-created element, so it can pass even if useSingleFileInput stops appending the input to the body.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/meteor/client/hooks/useSingleFileInput.spec.ts (1)

4-6: Prefer replaceChildren() over assigning innerHTML in test cleanup.

This keeps cleanup explicit and avoids HTML parsing code paths.

Proposed refactor
 afterEach(() => {
-	document.body.innerHTML = '';
+	document.body.replaceChildren();
 });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/client/hooks/useSingleFileInput.spec.ts` around lines 4 - 6,
Replace the test cleanup that assigns document.body.innerHTML = '' inside the
afterEach block with a call to document.body.replaceChildren() to avoid HTML
parsing code paths; update the afterEach handler (the one currently using
document.body.innerHTML) to call replaceChildren() so cleanup is explicit and
faster.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/meteor/client/hooks/useSingleFileInput.spec.ts`:
- Around line 9-19: The test currently creates and appends its own input element
instead of verifying the hook's behavior; update the spec so renderHook(() =>
useSingleFileInput(onSetFile)) runs, then query the document for the input the
hook should have created (e.g., document.querySelector('input[type="file"]') or
use getByRole/getByTestId) and assert that this found element is defined and has
style.display === 'none', removing the manual creation of input and any
assertions against it; ensure you still use the onSetFile mock to verify any
callbacks the hook should wire up.

---

Nitpick comments:
In `@apps/meteor/client/hooks/useSingleFileInput.spec.ts`:
- Around line 4-6: Replace the test cleanup that assigns document.body.innerHTML
= '' inside the afterEach block with a call to document.body.replaceChildren()
to avoid HTML parsing code paths; update the afterEach handler (the one
currently using document.body.innerHTML) to call replaceChildren() so cleanup is
explicit and faster.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 75dec42 and db8a786.

📒 Files selected for processing (5)
  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
  • apps/meteor/client/hooks/useSingleFileInput.ts
  • apps/meteor/client/views/admin/customSounds/AddCustomSound.tsx
  • apps/meteor/client/views/admin/customSounds/EditSound.tsx
  • apps/meteor/client/views/marketplace/AppInstallPage.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 (2)
**/*.{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/hooks/useSingleFileInput.spec.ts
  • apps/meteor/client/views/marketplace/AppInstallPage.tsx
  • apps/meteor/client/hooks/useSingleFileInput.ts
  • apps/meteor/client/views/admin/customSounds/AddCustomSound.tsx
  • apps/meteor/client/views/admin/customSounds/EditSound.tsx
**/*.spec.ts

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

**/*.spec.ts: Use descriptive test names that clearly communicate expected behavior in Playwright tests
Use .spec.ts extension for test files (e.g., login.spec.ts)

Files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
🧠 Learnings (18)
📓 Common learnings
Learnt from: ggazzo
Repo: RocketChat/Rocket.Chat PR: 35995
File: apps/meteor/app/api/server/v1/rooms.ts:1107-1112
Timestamp: 2026-02-23T17:53:18.785Z
Learning: In Rocket.Chat PR reviews, maintain strict scope boundaries—when a PR is focused on a specific endpoint (e.g., rooms.favorite), avoid reviewing or suggesting changes to other endpoints that were incidentally refactored (e.g., rooms.invite) unless explicitly requested by maintainers.
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Utilize Playwright fixtures (`test`, `page`, `expect`) for consistency in test files

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Group related tests in the same file

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `test.step()` for complex test scenarios to improve organization in Playwright tests

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Maintain test isolation between test cases in Playwright tests

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : All test files must be created in `apps/meteor/tests/e2e/` directory

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `expect` matchers for assertions (`toEqual`, `toContain`, `toBeTruthy`, `toHaveLength`, etc.) instead of `assert` statements in Playwright tests

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure tests run reliably in parallel without shared state conflicts

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `test.beforeAll()` and `test.afterAll()` for setup/teardown in Playwright tests

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,spec.ts} : Follow Page Object Model pattern consistently in Playwright tests

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Prefer web-first assertions (`toBeVisible`, `toHaveText`, etc.) in Playwright tests

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-12-16T17:29:45.163Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37834
File: apps/meteor/tests/e2e/page-objects/fragments/admin-flextab-emoji.ts:12-22
Timestamp: 2025-12-16T17:29:45.163Z
Learning: In page object files under `apps/meteor/tests/e2e/page-objects/`, always import `expect` from `../../utils/test` (Playwright's async expect), not from Jest. Jest's `expect` has a synchronous signature and will cause TypeScript errors when used with web-first assertions like `toBeVisible()`.

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure clean state for each test execution in Playwright tests

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2026-02-10T16:32:42.586Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 38528
File: apps/meteor/client/startup/roles.ts:14-14
Timestamp: 2026-02-10T16:32:42.586Z
Learning: In Rocket.Chat's Meteor client code, DDP streams use EJSON and Date fields arrive as Date objects; do not manually construct new Date() in stream handlers (for example, in sdk.stream()). Only REST API responses return plain JSON where dates are strings, so implement explicit conversion there if needed. Apply this guidance to all TypeScript files under apps/meteor/client to ensure consistent date handling in DDP streams and REST responses.

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
  • apps/meteor/client/hooks/useSingleFileInput.ts
📚 Learning: 2026-02-24T19:22:48.358Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 38493
File: apps/meteor/tests/e2e/omnichannel/omnichannel-send-pdf-transcript.spec.ts:66-67
Timestamp: 2026-02-24T19:22:48.358Z
Learning: In Playwright end-to-end tests (e.g., under apps/meteor/tests/e2e/...), prefer locating elements by translated text (getByText) and ARIA roles (getByRole) over data-qa attributes. If translation values change, update the corresponding test locators accordingly. Never use data-qa locators. This guideline applies to all Playwright e2e test specs in the repository and helps keep tests robust to UI text changes and accessible semantics.

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In the Rocket.Chat repository, do not reference Biome lint rules in code review feedback. Biome is not used even if biome.json exists; only reference Biome rules if there is explicit, project-wide usage documented. For TypeScript files, review lint implications without Biome guidance unless the project enables Biome rules.

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
  • apps/meteor/client/hooks/useSingleFileInput.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In this repository (RocketChat/Rocket.Chat), Biome lint rules are not used even if a biome.json exists. When reviewing TypeScript files (e.g., packages/ui-voip/src/providers/useMediaSession.ts), ensure lint suggestions do not reference Biome-specific rules. Rely on general ESLint/TypeScript lint rules and project conventions instead.

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
  • apps/meteor/client/hooks/useSingleFileInput.ts
📚 Learning: 2025-10-06T20:32:23.658Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37152
File: packages/apps-engine/tests/test-data/utilities.ts:557-573
Timestamp: 2025-10-06T20:32:23.658Z
Learning: In packages/apps-engine/tests/test-data/utilities.ts, the field name `isSubscripbedViaBundle` in the `IMarketplaceSubscriptionInfo` type should not be flagged as a typo, as it may match the upstream API's field name.

Applied to files:

  • apps/meteor/client/views/marketplace/AppInstallPage.tsx
🧬 Code graph analysis (4)
apps/meteor/client/hooks/useSingleFileInput.spec.ts (1)
apps/meteor/client/hooks/useSingleFileInput.ts (1)
  • useSingleFileInput (4-65)
apps/meteor/client/views/marketplace/AppInstallPage.tsx (1)
apps/meteor/client/hooks/useSingleFileInput.ts (1)
  • useSingleFileInput (4-65)
apps/meteor/client/views/admin/customSounds/AddCustomSound.tsx (1)
apps/meteor/client/hooks/useSingleFileInput.ts (1)
  • useSingleFileInput (4-65)
apps/meteor/client/views/admin/customSounds/EditSound.tsx (1)
apps/meteor/client/hooks/useSingleFileInput.ts (1)
  • useSingleFileInput (4-65)
🪛 ast-grep (0.41.0)
apps/meteor/client/hooks/useSingleFileInput.spec.ts

[warning] 4-4: Direct modification of innerHTML or outerHTML properties detected. Modifying these properties with unsanitized user input can lead to XSS vulnerabilities. Use safe alternatives or sanitize content first.
Context: document.body.innerHTML = ''
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://owasp.org/www-community/xss-filter-evasion-cheatsheet
- https://cwe.mitre.org/data/definitions/79.html

(dom-content-modification)

🔇 Additional comments (6)
apps/meteor/client/hooks/useSingleFileInput.spec.ts (1)

21-70: Good coverage for the refactored hook API.

The tests for explicit fileType, default image/*, click forwarding, and FormData callback flow look solid.

apps/meteor/client/hooks/useSingleFileInput.ts (1)

7-12: API refactor is clean and backward-safe on defaults.

Using options.fileType with default image/* preserves existing behavior while enabling explicit overrides.

apps/meteor/client/views/marketplace/AppInstallPage.tsx (1)

18-18: Call-site update matches the new hook contract.

Using { fileType: '.zip' } here correctly scopes chooser options for app package uploads.

apps/meteor/client/views/admin/customSounds/EditSound.tsx (2)

32-35: No actionable concern in this type-formatting-only change.


126-126: Hook invocation migration is correct.

This call now follows the new (onSetFile, fileField, options) shape and keeps the intended audio filter.

apps/meteor/client/views/admin/customSounds/AddCustomSound.tsx (1)

31-31: This call-site update is aligned with the new hook API.

The argument order and options object usage are consistent with the refactored useSingleFileInput.

Copy link
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 (2)
apps/meteor/client/hooks/useSingleFileInput.spec.ts (2)

5-7: Prefer DOM child cleanup over innerHTML in test teardown.

At Line 6, document.body.innerHTML = '' works, but replaceChildren() is safer/cleaner and avoids static-analysis security noise.

Suggested change
 afterEach(() => {
-    document.body.innerHTML = '';
+    document.body.replaceChildren();
 });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/client/hooks/useSingleFileInput.spec.ts` around lines 5 - 7,
Replace the test teardown that uses document.body.innerHTML = '' with a DOM-safe
cleanup call: in the afterEach callback (the anonymous function passed to
afterEach in useSingleFileInput.spec.ts) call document.body.replaceChildren() to
remove child nodes instead of resetting innerHTML; this avoids
security/static-analysis issues while preserving the same teardown behavior.

22-23: Optional: centralize input lookup with a null guard for clearer failures.

Repeated direct casts from querySelector can hide intent when setup fails. A small helper (assert + return typed input) would make failures more explicit and reduce duplication.

Also applies to: 30-31, 39-40, 53-54, 73-73, 102-104, 123-124

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

In `@apps/meteor/client/hooks/useSingleFileInput.spec.ts` around lines 22 - 23,
Create a small test helper (e.g., assertFileInput or getFileInputOrThrow) that
encapsulates document.querySelector('input[type="file"]') and throws a clear
error if the element is null, returning the value typed as HTMLInputElement;
replace the repeated direct casts in the spec with calls to that helper at each
assertion site so failures are explicit and duplication is removed.
🤖 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/hooks/useSingleFileInput.spec.ts`:
- Around line 5-7: Replace the test teardown that uses document.body.innerHTML =
'' with a DOM-safe cleanup call: in the afterEach callback (the anonymous
function passed to afterEach in useSingleFileInput.spec.ts) call
document.body.replaceChildren() to remove child nodes instead of resetting
innerHTML; this avoids security/static-analysis issues while preserving the same
teardown behavior.
- Around line 22-23: Create a small test helper (e.g., assertFileInput or
getFileInputOrThrow) that encapsulates
document.querySelector('input[type="file"]') and throws a clear error if the
element is null, returning the value typed as HTMLInputElement; replace the
repeated direct casts in the spec with calls to that helper at each assertion
site so failures are explicit and duplication is removed.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between db8a786 and 3f6a0eb.

📒 Files selected for processing (1)
  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{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/hooks/useSingleFileInput.spec.ts
**/*.spec.ts

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

**/*.spec.ts: Use descriptive test names that clearly communicate expected behavior in Playwright tests
Use .spec.ts extension for test files (e.g., login.spec.ts)

Files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
🧠 Learnings (21)
📓 Common learnings
Learnt from: ggazzo
Repo: RocketChat/Rocket.Chat PR: 35995
File: apps/meteor/app/api/server/v1/rooms.ts:1107-1112
Timestamp: 2026-02-23T17:53:18.785Z
Learning: In Rocket.Chat PR reviews, maintain strict scope boundaries—when a PR is focused on a specific endpoint (e.g., rooms.favorite), avoid reviewing or suggesting changes to other endpoints that were incidentally refactored (e.g., rooms.invite) unless explicitly requested by maintainers.
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Utilize Playwright fixtures (`test`, `page`, `expect`) for consistency in test files

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Group related tests in the same file

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Maintain test isolation between test cases in Playwright tests

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `test.step()` for complex test scenarios to improve organization in Playwright tests

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `expect` matchers for assertions (`toEqual`, `toContain`, `toBeTruthy`, `toHaveLength`, etc.) instead of `assert` statements in Playwright tests

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : All test files must be created in `apps/meteor/tests/e2e/` directory

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure tests run reliably in parallel without shared state conflicts

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `test.beforeAll()` and `test.afterAll()` for setup/teardown in Playwright tests

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure clean state for each test execution in Playwright tests

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to **/*.spec.ts : Use descriptive test names that clearly communicate expected behavior in Playwright tests

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-12-10T21:00:54.909Z
Learnt from: KevLehman
Repo: RocketChat/Rocket.Chat PR: 37091
File: ee/packages/abac/jest.config.ts:4-7
Timestamp: 2025-12-10T21:00:54.909Z
Learning: Rocket.Chat monorepo: Jest testMatch pattern '<rootDir>/src/**/*.spec.(ts|js|mjs)' is valid in this repo and used across multiple packages (e.g., packages/tools, ee/packages/omnichannel-services). Do not flag it as invalid in future reviews.

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2026-02-24T19:36:55.089Z
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:55.089Z
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/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,spec.ts} : Follow Page Object Model pattern consistently in Playwright tests

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Prefer web-first assertions (`toBeVisible`, `toHaveText`, etc.) in Playwright tests

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-12-16T17:29:45.163Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37834
File: apps/meteor/tests/e2e/page-objects/fragments/admin-flextab-emoji.ts:12-22
Timestamp: 2025-12-16T17:29:45.163Z
Learning: In page object files under `apps/meteor/tests/e2e/page-objects/`, always import `expect` from `../../utils/test` (Playwright's async expect), not from Jest. Jest's `expect` has a synchronous signature and will cause TypeScript errors when used with web-first assertions like `toBeVisible()`.

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Implement proper wait strategies for dynamic content in Playwright tests

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2026-02-10T16:32:42.586Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 38528
File: apps/meteor/client/startup/roles.ts:14-14
Timestamp: 2026-02-10T16:32:42.586Z
Learning: In Rocket.Chat's Meteor client code, DDP streams use EJSON and Date fields arrive as Date objects; do not manually construct new Date() in stream handlers (for example, in sdk.stream()). Only REST API responses return plain JSON where dates are strings, so implement explicit conversion there if needed. Apply this guidance to all TypeScript files under apps/meteor/client to ensure consistent date handling in DDP streams and REST responses.

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2026-02-24T19:22:48.358Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 38493
File: apps/meteor/tests/e2e/omnichannel/omnichannel-send-pdf-transcript.spec.ts:66-67
Timestamp: 2026-02-24T19:22:48.358Z
Learning: In Playwright end-to-end tests (e.g., under apps/meteor/tests/e2e/...), prefer locating elements by translated text (getByText) and ARIA roles (getByRole) over data-qa attributes. If translation values change, update the corresponding test locators accordingly. Never use data-qa locators. This guideline applies to all Playwright e2e test specs in the repository and helps keep tests robust to UI text changes and accessible semantics.

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In the Rocket.Chat repository, do not reference Biome lint rules in code review feedback. Biome is not used even if biome.json exists; only reference Biome rules if there is explicit, project-wide usage documented. For TypeScript files, review lint implications without Biome guidance unless the project enables Biome rules.

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In this repository (RocketChat/Rocket.Chat), Biome lint rules are not used even if a biome.json exists. When reviewing TypeScript files (e.g., packages/ui-voip/src/providers/useMediaSession.ts), ensure lint suggestions do not reference Biome-specific rules. Rely on general ESLint/TypeScript lint rules and project conventions instead.

Applied to files:

  • apps/meteor/client/hooks/useSingleFileInput.spec.ts
🧬 Code graph analysis (1)
apps/meteor/client/hooks/useSingleFileInput.spec.ts (1)
apps/meteor/client/hooks/useSingleFileInput.ts (1)
  • useSingleFileInput (4-65)
🪛 ast-grep (0.41.0)
apps/meteor/client/hooks/useSingleFileInput.spec.ts

[warning] 5-5: Direct modification of innerHTML or outerHTML properties detected. Modifying these properties with unsanitized user input can lead to XSS vulnerabilities. Use safe alternatives or sanitize content first.
Context: document.body.innerHTML = ''
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://owasp.org/www-community/xss-filter-evasion-cheatsheet
- https://cwe.mitre.org/data/definitions/79.html

(dom-content-modification)

🔇 Additional comments (1)
apps/meteor/client/hooks/useSingleFileInput.spec.ts (1)

18-33: Good coverage for the refactored API behavior.

These tests correctly exercise options.fileType (custom + default), dynamic rerender updates, and onSetFile/FormData behavior for selected vs empty files. Nice regression protection for the hook signature change.

Also applies to: 49-67, 69-84, 113-125

@dodaa08 dodaa08 requested a review from dougfabris February 28, 2026 09:27
@dodaa08
Copy link
Contributor Author

dodaa08 commented Feb 28, 2026

I've refactored useSingleFileInput to accept an options object as the third argument with an optional fileType property, defaulting to image/*. All existing call sites have been updated accordingly, Let me know if there's anything else you'd like changed!

@dodaa08
Copy link
Contributor Author

dodaa08 commented Mar 3, 2026

Hey @dougfabris , let know if any code changes are needed here whenever you review.

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.

2 participants