Skip to content

Truncated text component#1117

Merged
arkid15r merged 37 commits intoOWASP:mainfrom
yashgoyal0110:feat/TruncatedText-component
Mar 24, 2025
Merged

Truncated text component#1117
arkid15r merged 37 commits intoOWASP:mainfrom
yashgoyal0110:feat/TruncatedText-component

Conversation

@yashgoyal0110
Copy link
Contributor

@yashgoyal0110 yashgoyal0110 commented Mar 15, 2025

fixes: #1114

Screenshot 2025-03-16 at 1 38 31 AM

@yashgoyal0110 yashgoyal0110 marked this pull request as draft March 15, 2025 19:13
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 15, 2025

Summary by CodeRabbit

  • New Features

    • Introduced a new text display enhancement that automatically truncates long text with ellipses for a cleaner interface.
  • Refactor

    • Updated multiple sections including item, repository, and home page listings to leverage the enhanced text display for consistent presentation.
  • Tests

    • Implemented additional tests to ensure that text elements consistently apply proper overflow handling and display behavior.

Walkthrough

This pull request introduces a new reusable TruncatedText component designed to manage text overflow by truncating lengthy text with an ellipsis. The component is integrated into the ItemCardList, Home, and RepositoriesCard components, replacing direct text renderings. Additionally, a comprehensive set of unit tests for the TruncatedText component and end-to-end tests for verifying CSS truncation on the Home page have been added.

Changes

Files Change Summary
frontend/__tests__/unit/components/TruncatedText.test.tsx
frontend/__tests__/e2e/pages/Home.spec.ts
Added unit tests for the TruncatedText component and an end-to-end test verifying CSS properties (overflow, ellipsis, no-wrap) for truncated text in the Home page.
frontend/src/components/TruncatedText.tsx Introduced a new React functional component that manages text truncation. It uses a ref and ResizeObserver to dynamically check for overflow and sets a title attribute for tooltip functionality.
frontend/src/components/ItemCardList.tsx
frontend/src/pages/Home.tsx
frontend/src/components/RepositoriesCard.tsx
Modified existing components by replacing direct text rendering with the reusable TruncatedText component, ensuring consistent truncation behavior across various use cases. Additional styling classes (overflow-hidden) have been applied where necessary.

Assessment against linked issues

Objective Addressed Explanation
Implement a reusable TruncatedText component and integrate it for text overflow control (#1114)
Ensure the component uses title/tooltip for displaying full text when truncated (#1114)
Include unit and end-to-end tests to verify text truncation behavior (#1114)

Possibly related PRs

  • Issue resolved : #1068 Correction to overflow of name in usercard  #1070: The changes in the main PR, which introduce a new TruncatedText component and its associated tests, are related to the modifications in the retrieved PR that address text overflow in the UserCard component, as both involve handling text display and truncation logic.
  • Sidebar migration to chakra ui #1113: The changes in the main PR, which introduce a new test suite for the TruncatedText component, are related to the modifications in the retrieved PR that involve the use of the TruncatedText component in the ItemCardList and Home components, as they both directly interact with the same component.

Suggested reviewers

  • kasya

📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 39bf7bb and da5da20.

📒 Files selected for processing (1)
  • frontend/jest.setup.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/jest.setup.ts
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: CodeQL (python)
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: CodeQL (javascript-typescript)
  • GitHub Check: Run frontend unit tests
  • GitHub Check: Run backend tests

🪧 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 generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @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
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: 2

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7f661e3 and b3a7862.

📒 Files selected for processing (4)
  • frontend/__tests__/unit/components/TruncatedText.test.tsx (1 hunks)
  • frontend/src/components/ItemCardList.tsx (2 hunks)
  • frontend/src/components/TruncatedText.tsx (1 hunks)
  • frontend/src/pages/Home.tsx (5 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: CodeQL (python)
  • GitHub Check: Run frontend unit tests
  • GitHub Check: CodeQL (javascript-typescript)
  • GitHub Check: Run backend tests
🔇 Additional comments (9)
frontend/src/components/ItemCardList.tsx (2)

4-4: LGTM: Added import for the new TruncatedText component.

The import statement is correctly added to use the new component.


43-43: LGTM: Implemented text truncation for item titles.

Good implementation of the TruncatedText component with a reasonable maxLength of 40 characters. This will improve UI consistency by truncating potentially long item titles while displaying the full title in a tooltip on hover.

frontend/src/components/TruncatedText.tsx (1)

1-27: LGTM: Well-structured TruncatedText component.

The component is well-designed with appropriate props and implementation:

  • Takes required text and optional maxLength, className, and disabledTooltip props
  • Handles truncation logic cleanly
  • Uses a Tooltip for displaying the full text on hover
  • Properly manages conditional rendering based on text length

The implementation is clean, simple, and follows React best practices.

frontend/src/pages/Home.tsx (4)

32-32: LGTM: Added import for the new TruncatedText component.

The import statement is correctly added.


148-150: LGTM: Implemented text truncation for event names.

Good implementation of the TruncatedText component with a reasonable maxLength of 40 characters.


185-185: LGTM: Implemented text truncation for chapter names.

Good implementation of the TruncatedText component with a reasonable maxLength of 40 characters.


297-297: LGTM: Implemented text truncation for post titles.

Good implementation of the TruncatedText component with a reasonable maxLength of 40 characters.

frontend/__tests__/unit/components/TruncatedText.test.tsx (2)

1-22: LGTM: Comprehensive test coverage for TruncatedText component.

The test suite covers the main functionality of the component:

  • Rendering full text when shorter than maxLength
  • Truncating long text with ellipsis
  • Displaying tooltip on hover

21-21: Verify tooltip implementation in tests.

The test is checking for a title attribute, but the component is using a Tooltip component rather than setting a title attribute directly. This test might be passing incorrectly or relying on implementation details.

Consider using a tooltip testing library or verifying if the Tooltip component actually adds a title attribute to its children. If needed, modify the test to match the actual implementation.

Comment on lines 214 to 216
<h3 className="truncate text-wrap md:text-nowrap">
<TruncatedText text={project.name} maxLength={40} />
</h3>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove redundant heading element.

There's a redundant nesting of h3 elements. The parent element is already an h3, and another h3 is nested inside the anchor tag.

Apply this fix:

-<h3 className="mb-2 text-lg font-semibold">
  <a href={`/projects/${project.key}`} className="hover:underline">
-    <h3 className="truncate text-wrap md:text-nowrap">
      <TruncatedText text={project.name} maxLength={40} />
-    </h3>
  </a>
-</h3>
+<h3 className="mb-2 text-lg font-semibold">
+  <a href={`/projects/${project.key}`} className="hover:underline">
+    <span className="truncate text-wrap md:text-nowrap">
+      <TruncatedText text={project.name} maxLength={40} />
+    </span>
+  </a>
+</h3>
📝 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.

Suggested change
<h3 className="truncate text-wrap md:text-nowrap">
<TruncatedText text={project.name} maxLength={40} />
</h3>
<h3 className="mb-2 text-lg font-semibold">
<a href={`/projects/${project.key}`} className="hover:underline">
<span className="truncate text-wrap md:text-nowrap">
<TruncatedText text={project.name} maxLength={40} />
</span>
</a>
</h3>

@yashgoyal0110 yashgoyal0110 force-pushed the feat/TruncatedText-component branch 2 times, most recently from 269ff95 to 7598ca8 Compare March 15, 2025 20:00
@yashgoyal0110 yashgoyal0110 marked this pull request as ready for review March 15, 2025 20:04
@yashgoyal0110 yashgoyal0110 force-pushed the feat/TruncatedText-component branch from f5c0fac to 1c1dd11 Compare March 15, 2025 20:14
@yashgoyal0110 yashgoyal0110 force-pushed the feat/TruncatedText-component branch from 1c1dd11 to 269ff95 Compare March 15, 2025 20:16
@github-actions github-actions bot removed the backend label Mar 15, 2025
@yashgoyal0110 yashgoyal0110 marked this pull request as ready for review March 24, 2025 07:29
@yashgoyal0110 yashgoyal0110 requested a review from arkid15r March 24, 2025 07:29
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: 0

🧹 Nitpick comments (3)
frontend/src/components/TruncatedText.tsx (3)

3-11: Prop handling could be improved to support nullable text values.

The component correctly defines the props and uses useCallback for the truncation check function. However, it doesn't handle cases where text might be undefined or null, which could lead to issues.

Consider adding a fallback for text to handle undefined or null values:

-export const TruncatedText = ({ text, className = '' }: { text: string; className?: string }) => {
+export const TruncatedText = ({ text = '', className = '' }: { text?: string; className?: string }) => {
  const textRef = useRef<HTMLSpanElement>(null)

  const checkTruncation = useCallback(() => {
    const element = textRef.current
    if (element) {
-      element.title = text
+      element.title = text || ''
    }
  }, [text])

13-27: Effect setup is appropriate but consider optimizing resize handlers.

The useEffect hook correctly sets up and cleans up event listeners and the ResizeObserver. However, both the ResizeObserver and the window resize event listener trigger the same function, which might be redundant in some cases.

Since ResizeObserver already captures element size changes, you might only need the window resize listener for specific cases where the ResizeObserver might not trigger. Consider if both are necessary for your use case, or if you can rely primarily on the ResizeObserver.


1-37: Consider adding a check for actual text truncation.

The component currently always sets the title attribute regardless of whether the text is actually truncated. For better performance and user experience, consider adding a check to determine if the text is actually truncated before setting the title.

You could modify the checkTruncation function to check if the text is actually truncated:

  const checkTruncation = useCallback(() => {
    const element = textRef.current
    if (element) {
-      element.title = text
+      // Only set title if text is truncated
+      if (element.scrollWidth > element.clientWidth) {
+        element.title = text
+      } else {
+        element.removeAttribute('title')
+      }
    }
  }, [text])

However, based on the previous comments, it was agreed that "It's fine to always have the title set to text," so this suggestion is optional.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 38808c6 and 79bb085.

📒 Files selected for processing (2)
  • frontend/src/components/RepositoriesCard.tsx (2 hunks)
  • frontend/src/components/TruncatedText.tsx (1 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
frontend/src/components/RepositoriesCard.tsx (1)
frontend/src/components/TruncatedText.tsx (1)
  • TruncatedText (3-37)
🔇 Additional comments (3)
frontend/src/components/RepositoriesCard.tsx (2)

16-16: Added import for TruncatedText component appropriately.

The import has been correctly added for the TruncatedText component that will be used to handle text truncation.


63-63: Good implementation of TruncatedText for repository names.

Replacing the direct text rendering with the TruncatedText component is a good approach. This will handle repository names that are too long by truncating them with an ellipsis and showing the full name on hover via the title attribute, improving the user experience.

frontend/src/components/TruncatedText.tsx (1)

29-36: CSS classes for truncation are well-implemented.

The span element correctly uses appropriate CSS classes for text truncation (overflow-hidden, truncate, text-ellipsis, whitespace-nowrap). The component also accepts an optional className prop to allow for additional styling, which provides good flexibility.

@arkid15r arkid15r marked this pull request as draft March 24, 2025 15:53
@yashgoyal0110 yashgoyal0110 marked this pull request as ready for review March 24, 2025 16:12
@yashgoyal0110
Copy link
Contributor Author

I have fixed test-cases

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 (2)
frontend/__tests__/unit/components/TruncatedText.test.tsx (2)

15-20: Consider validating the className prop.

While your test correctly checks the text content and title attribute, it doesn't explicitly verify that the className prop is properly passed to the component. Since your test provides "w-auto" as className, consider adding an assertion to check it's applied.

  test('renders full text when it fits within the container', () => {
    render(<TruncatedText text="Short text" className="w-auto" />)
    const textElement = screen.getByText('Short text')
    expect(textElement).toBeInTheDocument()
    expect(textElement).toHaveAttribute('title', 'Short text')
+   expect(textElement).toHaveClass('w-auto')
  })

12-27: Add tests for ResizeObserver functionality and edge cases.

Your test coverage could be improved by adding tests for:

  1. Verification that the ResizeObserver is created and cleaned up properly
  2. Testing behavior with empty strings or very short text
  3. Testing how the component handles window resize events

Example of testing cleanup:

test('cleans up observer and event listener on unmount', () => {
  const { unmount } = render(<TruncatedText text={longText} />)
  
  // Mock the cleanup functions
  const disconnectSpy = jest.spyOn(global.ResizeObserver.prototype, 'disconnect')
  const removeEventListenerSpy = jest.spyOn(window, 'removeEventListener')
  
  // Unmount the component
  unmount()
  
  // Verify cleanup was called
  expect(disconnectSpy).toHaveBeenCalled()
  expect(removeEventListenerSpy).toHaveBeenCalledWith('resize', expect.any(Function))
})
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 79bb085 and e8ebf83.

📒 Files selected for processing (1)
  • frontend/__tests__/unit/components/TruncatedText.test.tsx (1 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
frontend/__tests__/unit/components/TruncatedText.test.tsx (1)
frontend/src/components/TruncatedText.tsx (1)
  • TruncatedText (3-37)
🔇 Additional comments (1)
frontend/__tests__/unit/components/TruncatedText.test.tsx (1)

4-10: Good implementation of the ResizeObserver mock.

You've correctly implemented a mock for ResizeObserver which is essential since it's not available in the JSDOM testing environment. The mock provides all the necessary methods that the component will call.

Copy link
Collaborator

@arkid15r arkid15r left a comment

Choose a reason for hiding this comment

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

You keep ignoring my requests to work according to the recommended guidelines. After this PR in order to avoid resource/time wasting I'm going to start approving the tests runs once per day only.

@arkid15r arkid15r marked this pull request as draft March 24, 2025 17:04
@yashgoyal0110 yashgoyal0110 marked this pull request as ready for review March 24, 2025 17:33
@yashgoyal0110
Copy link
Contributor Author

Screenshot 2025-03-24 at 11 02 49 PM

@arkid15r arkid15r enabled auto-merge March 24, 2025 21:33
@sonarqubecloud
Copy link

Copy link
Collaborator

@arkid15r arkid15r left a comment

Choose a reason for hiding this comment

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

LGTM

@arkid15r arkid15r added this pull request to the merge queue Mar 24, 2025
Merged via the queue into OWASP:main with commit ec54a5f Mar 24, 2025
18 checks passed
@yashgoyal0110 yashgoyal0110 deleted the feat/TruncatedText-component branch March 26, 2025 13:17
Rajgupta36 pushed a commit to Rajgupta36/Nest-n that referenced this pull request Mar 30, 2025
* commit

* Update pnpm-lock.yaml

* Update vite.config.ts

* Update package.json

* truncate text component

* commit

* commit

* commit

* commit

* commit

* commit

* commit

* commit

* commit

* commit

* fixed e2e and improved truncate component

* fixed pre-commit

* comit

* comit

* commit

* fixed unit tests

* fixed unit test

* commit

* Update code

---------

Co-authored-by: Kate Golovanova <kate@kgthreads.com>
Co-authored-by: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com>
Co-authored-by: Arkadii Yakovets <arkadii.yakovets@owasp.org>
shdwcodr pushed a commit to shdwcodr/Nest that referenced this pull request Jun 5, 2025
* commit

* Update pnpm-lock.yaml

* Update vite.config.ts

* Update package.json

* truncate text component

* commit

* commit

* commit

* commit

* commit

* commit

* commit

* commit

* commit

* commit

* fixed e2e and improved truncate component

* fixed pre-commit

* comit

* comit

* commit

* fixed unit tests

* fixed unit test

* commit

* Update code

---------

Co-authored-by: Kate Golovanova <kate@kgthreads.com>
Co-authored-by: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com>
Co-authored-by: Arkadii Yakovets <arkadii.yakovets@owasp.org>
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.

Address text overflow/truncation issue

3 participants