Brijesh619 commented on code in PR #728:
URL: https://github.com/apache/atlas/pull/728#discussion_r3967021150


##########
dashboard/src/views/DashboardOverview/__tests__/LatestEntitiesList.test.tsx:
##########
@@ -624,4 +622,89 @@ describe('LatestEntitiesList', () => {
                )
                expect(screen.getByText('Created today')).toBeInTheDocument()
        })
+
+       it('renders fallback Typography when detailHref is absent (no guid)', 
() => {
+               render(
+                       <MemoryRouter>
+                               <LatestEntitiesList
+                                       entities={[
+                                               {
+                                                       name: 
'EntityWithoutGuid',
+                                                       typeName: 'T',
+                                                       attributes: { 
__timestamp: Date.now() },
+                                               },
+                                       ]}
+                               />
+                       </MemoryRouter>,
+               )
+               const fallbackText = screen.getByText('EntityWithoutGuid')
+               expect(fallbackText).toBeInTheDocument()
+               expect(fallbackText.tagName).toBe('SPAN')
+               
expect(fallbackText).toHaveClass('latest-entities-entity-name-fallback')
+       })
+
+
+       it('renders extremely long entity name without crashing', () => {
+               const longName = 'A'.repeat(500)
+               render(
+                       <MemoryRouter>
+                               <LatestEntitiesList
+                                       entities={[
+                                               {
+                                                       guid: 'g1',
+                                                       name: longName,
+                                                       typeName: 'T',
+                                                       attributes: { 
__timestamp: Date.now() },
+                                               },
+                                       ]}
+                               />
+                       </MemoryRouter>,
+               )
+               const link = screen.getByRole('link', { name: longName })
+               expect(link).toBeInTheDocument()
+               expect(link.textContent).toBe(longName)
+               
+               const span = link.parentElement
+               expect(span).toHaveStyle('overflow: hidden')
+               expect(span).toHaveStyle('text-overflow: ellipsis')
+               expect(span).toHaveStyle('white-space: nowrap')
+       })
+
+       it('renders gracefully when typeName is missing', () => {
+               render(
+                       <MemoryRouter>
+                               <LatestEntitiesList
+                                       entities={[
+                                               {
+                                                       guid: 'g1',
+                                                       name: 'NamelessType',
+                                                       attributes: { 
__timestamp: Date.now() },
+                                               },
+                                       ]}
+                               />
+                       </MemoryRouter>,
+               )
+               expect(screen.getByText('(Entity)')).toBeInTheDocument()
+       })
+
+       it('renders extremely long typeName without breaking layout', () => {
+               const longTypeName = 'B'.repeat(300)
+               render(
+                       <MemoryRouter>
+                               <LatestEntitiesList
+                                       entities={[
+                                               {
+                                                       guid: 'g1',
+                                                       name: 
'EntityWithLongType',
+                                                       typeName: longTypeName,
+                                                       attributes: { 
__timestamp: Date.now() },
+                                               },
+                                       ]}
+                               />
+                       </MemoryRouter>,
+               )
+               const typeElement = screen.getByText(`(${longTypeName})`)
+               expect(typeElement).toBeInTheDocument()
+               
expect(typeElement.parentElement).toHaveClass('latest-entities-type-wrapper')
+       })

Review Comment:
   I've updated LatestEntitiesList.test.tsx to fill in those remaining gaps!
   
   Here's what was done:
   
   Tooltip on hover for long names: The renders extremely long entity name 
without crashing test now mocks the scrollWidth and clientWidth limits, forces 
a tooltip render via mouseEnter and mouseOver, advances the MUI enterDelay 
timer, and finally asserts that the tooltip text (multiple elements with the 
long name) successfully renders!
   Combined long entity name and long typeName: Added a new test, renders both 
extremely long entity name and extremely long typeName without layout break, 
that explicitly tests the layout collision scenario and asserts that both the 
name wrapper and type wrapper classes correctly apply side-by-side without 
crashing.
   The other gaps mentioned (duplicate fallback testing, and wrapper class 
assertions) were actually handled implicitly in my previous fixes to 
consolidate the fallback tests and shift the layout CSS fully into SCSS.
   



##########
dashboard/src/components/__tests__/muiComponents.test.tsx:
##########
@@ -21,11 +21,12 @@
  */
 
 import React from 'react'
-import { render, screen, fireEvent } from '@testing-library/react'
+import { render, screen, fireEvent, act } from '@testing-library/react'

Review Comment:
   I have filled in those gaps in the muiComponents.test.tsx file! I added the 
three missing test cases for the OverflowTooltip component:
   
   disconnects ResizeObserver on unmount: Verifies that disconnect() is 
correctly called on the observer when the component is unmounted.
   applies wrapperClassName to the wrapper: Ensures that custom class names are 
properly propagated to the root tooltip wrapper.
   updates overflow state when title prop changes: Checks that the tooltip 
overflow state is re-evaluated and updated properly when its content/title 
changes.
   I also updated the global ResizeObserver mock in the tests to cleanly expose 
the mocked disconnect and observe functions so they can be asserted against 
properly. I've run the tests to make sure they pass perfectly!



##########
dashboard/src/components/muiComponents.tsx:
##########
@@ -68,58 +71,97 @@ const LightTooltip = styled(({ className, ...props }: any) 
=> (
   }
 }));
 
-interface ButtonProps {
-  children?: any;
-  variant?: string;
-  color: string;
-  onClick: any;
-  sx?: any;
-  size?: string;
-  endIcon?: any;
-  startIcon?: any;
-  className?: string;
-  disabled?: boolean;
+
+interface OverflowTooltipProps extends Omit<TooltipProps, "children"> {
+  children: React.ReactElement;
+  wrapperSx?: SxProps<Theme>;
+  wrapperClassName?: string;
 }
 
+const OverflowTooltip = ({ title, children, wrapperSx, wrapperClassName, 
...props }: OverflowTooltipProps) => {
+  const textElementRef = React.useRef<HTMLElement>(null);
+  const [isOverflowed, setIsOverflowed] = React.useState(false);
+
+  const checkOverflow = React.useCallback(() => {
+    if (textElementRef.current) {
+      const el = textElementRef.current;
+      setIsOverflowed(
+        el.scrollWidth > el.clientWidth || 
+        el.scrollWidth > el.getBoundingClientRect().width
+      );
+    }
+  }, []);
+
+  React.useEffect(() => {
+    checkOverflow();
+    const element = textElementRef.current;
+    if (element) {
+      // One ResizeObserver per instance — acceptable for small lists (e.g. 
dashboard widgets).
+      // If this component is used in large virtualized lists, consider 
lifting a shared
+      // ResizeObserver to a context provider to reduce observer count.
+      const resizeObserver = new ResizeObserver(() => checkOverflow());
+      resizeObserver.observe(element);
+      return () => resizeObserver.disconnect();
+    }
+  }, [title, checkOverflow]);
+
+  const child = (
+    <Box

Review Comment:
   I've fully stripped out the layout rules (display, minWidth, and width) from 
OverflowTooltip's inline sx prop as requested, keeping it completely generic 
and only passing through wrapperSx.
   
   The display: block and other SCSS rules defined on 
.latest-entities-name-wrapper and .latest-entities-type-wrapper are now in full 
control of the layout and truncation, resolving the conflict. All tests still 
pass!



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to