pawarprasad123 commented on code in PR #688:
URL: https://github.com/apache/atlas/pull/688#discussion_r3929793670


##########
dashboard/src/redux/slice/sessionSlice.ts:
##########
@@ -74,7 +90,29 @@ const sessionSlice = createSlice({
       builder.addCase(fetchSessionData.rejected, (state, action) => {
         state.sessionObj = {
           loading: false,
-          data: null,
+          data: null as Record<string, unknown> | null,
+          error: (action.payload as string) || action.error?.message || 'An 
error occurred'
+        };
+      }),
+      builder.addCase(fetchVersionData.pending, (state) => {
+        // Preserve existing state.versionData.data on pending 
(stale-while-revalidate)
+        state.versionData.loading = true;
+        state.versionData.error = null;
+      }),
+      builder.addCase(
+        fetchVersionData.fulfilled,
+        (state, action: PayloadAction<DynamicData>) => {
+          state.versionData = {
+            loading: false,
+            data: action.payload,
+            error: null
+          };
+        }
+      ),
+      builder.addCase(fetchVersionData.rejected, (state, action) => {

Review Comment:
   fetchVersionData.rejected clears data to null, but pending retains it. 
Should rejected also keep stale data so the footer doesn't flash empty on 
transient network errors?



##########
dashboard/src/views/SideBar/SideBarTree/SideBarTree.tsx:
##########
@@ -287,1027 +336,1045 @@ const BarTreeView: FC<{
   sideBarOpen,
   searchTerm,
   loader,
+  isPopover,
 }) => {
-  const dispatch = useAppDispatch();
-  const { savedSearchData }: any = useAppSelector(
-    (state: any) => state.savedSearch
-  );
-  const { bmguid } = useParams();
-  const location = useLocation();
-  const navigate = useNavigate();
-  const searchParams = new URLSearchParams(location.search);
-  const [expand, setExpand] = useState<null | HTMLElement>(null);
-  const [selectedNode, setSelectedNode] = useState<{
-    type: string | null;
-    tag: string | null;
-    relationship: string | null;
-    businessMetadata: string | null;
-  }>({
-    type: null,
-    tag: null,
-    relationship: null,
-    businessMetadata: null,
-  });
-
-  const [openModal, setOpenModal] = useState<boolean>(false);
-  const toastId: any = useRef(null);
-  const open = Boolean(expand);
-  const [expandedItems, setExpandedItems] = useState<string[]>([]);
-  const [tagModal, setTagModal] = useState<boolean>(false);
-  const [glossaryModal, setGlossaryModal] = useState<boolean>(false);
-  const { businessMetaData }: any = useAppSelector(
-    (state: any) => state.businessMetaData
-  );
-
-  const filteredData = useMemo(() => {
-    return treeData.filter((node) => {
-      return (
-        node.label?.toLowerCase().includes(searchTerm.toLowerCase()) ||
-        (node.children &&
-          node.children.some((child) =>
-            child.label?.toLowerCase().includes(searchTerm.toLowerCase())
-          ))
-      );
+    const { savedSearchData }: any = useAppSelector(

Review Comment:
   Multiple any usages remain despite PR description claiming zero-any. Either 
refactor these selectors/reducers or update the PR description scope.



##########
dashboard/src/views/SideBar/SideBarBody.tsx:
##########
@@ -199,97 +232,145 @@ const SideBarBody = (props: {
   });
 
   const matched = matchRoutes(routeConfig, location.pathname);
+  const isMatched = !!matched;
+
+  const rightSideContent = useMemo(() => (
+    <Stack height="auto" minHeight="100%">
+      <div className="layout-header-container">
+        <Suspense fallback={null}>
+          <Header
+            handleOpenModal={handleOpenModal}
+            handleOpenAboutModal={handleOpenAboutModal}
+          />
+        </Suspense>
+      </div>
+      <div className="layout-content-container">
+        {isMatched || location.pathname.includes("!") ? (
+          <Suspense
+            fallback={
+              <div className="layout-loading-container">
+                <CircularProgress
+                  color="primary"
+                  className="sidebar-circular-progress"
+                />
+              </div>
+            }
+          >
+            <ErrorBoundaryWithNavigate
+              history={history}
+              key={location.pathname}
+            >
+              <Outlet />{" "}
+            </ErrorBoundaryWithNavigate>
+          </Suspense>
+        ) : (
+          <ErrorPage errorCode="404" />
+        )}
+      </div>
+    </Stack>
+  ), [isMatched, location.pathname, history, handleOpenModal, 
handleOpenAboutModal]);
 
   return (
     <Stack
       flexDirection="row"
       className="sidebar-box"
-      sx={{ overflow: "hidden" }}
     >
       <CssBaseline />
 
       <Drawer
-        sx={{
-          width: position,
-          flexShrink: 0,
-          minHeight: "calc(100vh - 64px)",
-          minWidth: "30px",
-          ...(open == false && {
-            transform: `translateX(calc(-${position} + 30px)) !important`,
-          }),
-          ...(open == false && { visibility: "visible !important" }),
-
-          "& .MuiDrawer-paper": {
-            background: "#034858",
-            boxSizing: "border-box",
-            overflow: "hidden",
-            position: "fixed",
-            top: "0",
-            transition: "none !important",
-            ...(open == false && {
-              transform: `translateX(30px) !important`,
-            }),
-            ...(open == false && { visibility: "visible !important" }),
-          },
-        }}
+        className={`sidebar-drawer ${open ? "open" : "closed"}`}
         PaperProps={{
-          style: { width: position, minWidth: "30px" },
+          className: "sidebar-drawer-paper"
         }}
         variant="persistent"
         anchor="left"
         open={open}
       >
-        <Stack
-          sx={{
-            height: "100vh",
-            width: "100%",
-            backgroundColor: "#034858",
-          }}
-        >
-          {/* Collapsed sidebar logo */}
+        <Stack className="sidebar-stack">
+          {/* Collapsed sidebar logo and module icons */}
           {!open && (
-            <div
-              style={{
-                width: "100%",
-                textAlign: "center",
-                paddingLeft: "12px",
-                display: "flex",
-                alignItems: "center",
-                justifyContent: "center",
-                minHeight: "64px",
-                cursor: "pointer",
-                boxSizing: "border-box",
-              }}
-              role="button"
-              tabIndex={0}
-              aria-label="Atlas home — refresh dashboard"
-              onClick={handleAtlasLogoClick}
-              onKeyDown={handleAtlasLogoKeyDown}
-              data-cy="apache-atlas-logo-collapsed"
+            <Stack
+              alignItems="center"
+              className="sidebar-mini-module-container"
             >
-              <img
-                src={apacheAtlasLogo}
-                alt="Apache Atlas logo"
-                style={{
-                  width: "29px",
-                  height: "auto",
-                  maxWidth: "100%",
-                  display: "block",
+              <div
+                className="collapsed-logo-container"
+                role="button"
+                tabIndex={0}
+                aria-label="Atlas home — refresh dashboard"
+                onClick={handleAtlasLogoClick}
+                onKeyDown={handleAtlasLogoKeyDown}
+                data-cy="apache-atlas-logo-collapsed"
+              >
+                <img
+                  src={apacheAtlasLogo}
+                  alt="Apache Atlas logo"
+                  className="collapsed-logo-img"
+                />
+              </div>
+
+              {/* Module Icons for Mini Drawer */}
+              <Stack alignItems="stretch" gap="1rem" 
className="sidebar-module-stack">
+                {/* Search */}
+                <Box className="sidebar-module-box">
+                  <Tooltip title="Search" placement="right">
+                    <IconButton aria-label="Expand sidebar search" onClick={() 
=> { setOpen(true); handlePopoverClose(); }} className="sidebar-module-btn">
+                      <img src="/img/sidebar-icons/icon-search.svg" 
className="sidebar-module-icon" alt="search" />
+                    </IconButton>
+                  </Tooltip>
+                </Box>
+
+                {modules.filter(m => m.isVisible).map(m => (
+                  <Box
+                    key={m.id}
+                    className={`sidebar-module-box ${m.isActive ? 
"sidebar-icon-active" : ""}`}
+                  >
+                    <Tooltip title={m.title} placement="right">
+                      <IconButton aria-haspopup="dialog" aria-label={m.title} 
aria-expanded={activePopover === m.id} onClick={(e) => handlePopoverOpen(e, 
m.id)} className={`sidebar-module-btn ${m.isActive ? "active" : ""}`}>
+                        <img src={m.iconUrl} className="sidebar-module-icon" 
alt={m.title.toLowerCase()} />
+                      </IconButton>
+                    </Tooltip>
+                  </Box>
+                ))}
+              </Stack>
+
+              <Popover
+                marginThreshold={16}
+                open={Boolean(activePopover) && activePopover !== ""}
+                anchorEl={popoverAnchor}
+                onClose={handlePopoverClose}
+                anchorOrigin={{
+                  vertical: isBottomHalf ? "bottom" : "top",
+                  horizontal: "right"
+                }}
+                transformOrigin={{
+                  vertical: isBottomHalf ? "bottom" : "top",
+                  horizontal: "left"
+                }}
+                PaperProps={{
+                  className: `sidebar-popover-paper ${isBottomHalf ? 
"bottom-half" : "top-half"}`,
+                  style: { maxHeight: popoverMaxHeight }
                 }}
-              />
-            </div>
+              >
+                {renderPopoverSearch()}
+                <div className="sidebar-module-icon-container">
+                  <Suspense fallback={<TreeSkeletonLoader count={2} />}>

Review Comment:
   Popover mounts a second tree instance while the hidden wrapper keeps the 
first. This doubles effects/Redux work. Can we portal/reuse the existing tree 
instead of duplicating? Test at line 696 confirms 2 instances.



##########
dashboard/src/styles/sidebar.scss:
##########
@@ -135,41 +153,33 @@
   color: v.$text-grey;
 }
 
-.sidebar-dragger {
-  position: inherit;
-  min-width: 2px;
-  width: 2px;
-  background-color: #f4f7f9;
-  cursor: col-resize;
-  padding: 4px 0 0;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  z-index: 999;
-  clear: both;
-}
 
-.sidebar-dragger:hover {
-  background: #4a90e2;
-}
 
 .tree-item-label {
-  width: calc(100% - 50px);
+  flex: 1;
+  min-width: 0;
   text-overflow: ellipsis;
   overflow: hidden;
   font-size: 14px;
   line-height: 29px;
   height: 29px;
+  white-space: nowrap;
 }
 
 .sidebar-wrapper {
-  background: #034858 !important;
+  background: v.$sidebar-bg !important;
   top: 20px;
   height: 100%;
   overflow-y: auto;
-  padding-bottom: 16px;
+  overflow-x: hidden;
+  flex: 1;
+  padding-bottom: 48px;
   padding-left: 8px;
   padding-right: 8px;
+
+  &--hidden {

Review Comment:
   PR description mentions "visibility hooks" but implementation uses display: 
none. Consider visibility: hidden; position: absolute; width: 0; overflow: 
hidden if layout measurement is needed, or update the description.



##########
dashboard/src/views/SideBar/SideBarTree/SideBarTree.tsx:
##########
@@ -287,1027 +336,1045 @@ const BarTreeView: FC<{
   sideBarOpen,
   searchTerm,
   loader,
+  isPopover,
 }) => {
-  const dispatch = useAppDispatch();
-  const { savedSearchData }: any = useAppSelector(
-    (state: any) => state.savedSearch
-  );
-  const { bmguid } = useParams();
-  const location = useLocation();
-  const navigate = useNavigate();
-  const searchParams = new URLSearchParams(location.search);
-  const [expand, setExpand] = useState<null | HTMLElement>(null);
-  const [selectedNode, setSelectedNode] = useState<{
-    type: string | null;
-    tag: string | null;
-    relationship: string | null;
-    businessMetadata: string | null;
-  }>({
-    type: null,
-    tag: null,
-    relationship: null,
-    businessMetadata: null,
-  });
-
-  const [openModal, setOpenModal] = useState<boolean>(false);
-  const toastId: any = useRef(null);
-  const open = Boolean(expand);
-  const [expandedItems, setExpandedItems] = useState<string[]>([]);
-  const [tagModal, setTagModal] = useState<boolean>(false);
-  const [glossaryModal, setGlossaryModal] = useState<boolean>(false);
-  const { businessMetaData }: any = useAppSelector(
-    (state: any) => state.businessMetaData
-  );
-
-  const filteredData = useMemo(() => {
-    return treeData.filter((node) => {
-      return (
-        node.label?.toLowerCase().includes(searchTerm.toLowerCase()) ||
-        (node.children &&
-          node.children.some((child) =>
-            child.label?.toLowerCase().includes(searchTerm.toLowerCase())
-          ))
-      );
+    const { savedSearchData }: any = useAppSelector(
+      (state: any) => state.savedSearch
+    );
+    const { bmguid } = useParams();
+    const dispatch = useAppDispatch();
+    const location = useLocation();
+    const navigate = useNavigate();
+    const searchParams = new URLSearchParams(location.search);
+    const [expand, setExpand] = useState<null | HTMLElement>(null);
+    const [selectedNode, setSelectedNode] = useState<SelectedNode>({
+      type: null,
+      tag: null,
+      relationship: null,
+      businessMetadata: null,
+      term: null,
+      customFilter: null,
     });
-  }, [treeData, searchTerm]);
 
-  const displayTreeName = useMemo(() => {
-    return treeName === "CustomFilters" ? "Custom Filters" : treeName
-  }, [treeName]);
+    const [openModal, setOpenModal] = useState<boolean>(false);
+    const toastId: any = useRef(null);

Review Comment:
   toastId: any = useRef(null) — type as useRef<number | string | null>(null) 
per AGENTS.md strict typing. Same for lines 603, 904.



##########
dashboard/src/styles/dashboard.scss:
##########
@@ -0,0 +1,459 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+.admin-audit-table-element-1 {
+       /* sx */
+       margin-top: 13px !important;
+       margin-left: 13px !important;
+}
+
+.add-validity-period-card-2 {
+       /* sx */
+       margin-bottom: 2rem;
+}
+
+.add-validity-period-custom-button-3 {
+       /* sx */
+       align-self: flex-end;
+}
+
+.add-validity-period-stack-4 {
+       /* sx */
+       min-height: 56px;
+}
+
+.add-validity-period-icon-button-5 {
+       /* sx */
+       display: inline-flex;
+       position: relative;
+       padding: 4px;
+       margin-left: 4px;
+       margin-top: 1.5rem !important;
+}
+
+.dash-board-stack-6 {
+       /* sx */
+       box-sizing: border-box;
+       overflow: hidden;
+}
+
+.dash-board-stack-7 {
+       /* sx */
+       flex-shrink: 0;
+       margin-bottom: 16px;
+}
+
+.dash-board-stack-8 {
+       /* sx */
+       min-width: 0;
+}
+
+.classification-distribution-card-box-9 {
+       /* sx */
+       padding: 12px;
+       background-color: #ffffff;

Review Comment:
   Hardcoded #ffffff and rgba shadows — prefer SCSS variables from 
variables.scss for theme consistency.



##########
dashboard/src/views/SideBar/__tests__/SideBarBody.test.tsx:
##########
@@ -622,18 +683,227 @@ describe('SideBarBody', () => {
     });
   });
 
-  describe('Window Resize', () => {
-    it('should handle window resize for drawer width constraints', () => {
-      // Mock window.innerWidth
-      Object.defineProperty(window, 'innerWidth', {
-        writable: true,
-        configurable: true,
-        value: 1920
+
+
+  describe('Collapsed Sidebar Popovers', () => {
+    beforeEach(() => {
+      // Start with closed drawer to see popover icons
+      renderWithProviders();
+      const toggleButton = 
screen.getByTestId('KeyboardDoubleArrowLeftIcon').closest('button');
+      fireEvent.click(toggleButton!);
+    });
+
+    it('should open correct popover and document that it mounts a duplicate 
tree instance (remount behavior)', async () => {
+      // Find the glossary icon and click it
+      const glossaryIcon = screen.getByAltText('glossary');
+      fireEvent.click(glossaryIcon.closest('button')!);
+
+      await waitFor(() => {
+        // Document remount behavior: The glossary tree is rendered TWICE:
+        // 1. The original instance inside the hidden sidebar-wrapper
+        // 2. A new separate instance mounted inside the Popover
+        const glossaryTrees = screen.getAllByTestId('glossary-tree');
+        expect(glossaryTrees.length).toBe(2);
+      });
+    });
+
+    it('should share search term between sidebar and popover', async () => {
+      // Re-open sidebar to access main search input
+      const toggleOpenButton = 
screen.getByTestId('KeyboardDoubleArrowRightIcon').closest('button');
+      fireEvent.click(toggleOpenButton!);
+
+      // Set search term in the main search bar
+      const searchInput = screen.getAllByPlaceholderText('Search')[0];
+      fireEvent.change(searchInput, { target: { value: 'popover_search' } });
+
+      // Close sidebar
+      const toggleCloseButton = 
screen.getByTestId('KeyboardDoubleArrowLeftIcon').closest('button');
+      fireEvent.click(toggleCloseButton!);
+
+      // Click entities icon
+      const entitiesIcon = screen.getByAltText('entities');
+      fireEvent.click(entitiesIcon.closest('button')!);
+
+      await waitFor(() => {
+        // Popover should receive the search term
+        const entitiesTree = screen.getAllByTestId('entities-tree').find(
+          el => el.textContent?.includes('Search: popover_search')
+        );
+        expect(entitiesTree).toBeInTheDocument();
+      });
+    });
+
+    it('should close popover when clicking outside', async () => {
+      // Open glossary popover
+      const glossaryIcon = screen.getByAltText('glossary');
+      fireEvent.click(glossaryIcon.closest('button')!);
+
+      await waitFor(() => {
+        
expect(screen.getAllByTestId('glossary-tree').length).toBeGreaterThan(0);
+      });
+
+      const backdrop = document.querySelector('.MuiBackdrop-root');
+      expect(backdrop).toBeInTheDocument();
+      if (backdrop) {
+        fireEvent.click(backdrop);
+      }
+
+      await waitFor(() => {
+        expect(screen.getAllByTestId('glossary-tree')).toHaveLength(1);
       });
+    });
+
+    it('should close popover on Escape key press', async () => {
+      // Open glossary popover
+      const glossaryIcon = screen.getByAltText('glossary');
+      fireEvent.click(glossaryIcon.closest('button')!);
+
+      await waitFor(() => {
+        
expect(screen.getAllByTestId('glossary-tree').length).toBeGreaterThan(0);
+      });
+
+      // Press Escape to close the popover
+      // MUI Popover listens for Escape on the document or active element
+      fireEvent.keyDown(document.activeElement || document.body, { key: 
'Escape', code: 'Escape' });
+
+      await waitFor(() => {
+        expect(screen.getAllByTestId('glossary-tree')).toHaveLength(1);
+      });
+    });
+
+    it('should NOT open popover when sidebar is expanded', async () => {
+      // Re-open sidebar that was closed in beforeEach
+      const toggleOpenButton = 
screen.getByTestId('KeyboardDoubleArrowRightIcon').closest('button');
+      fireEvent.click(toggleOpenButton!);
+
+      // Ensure sidebar is expanded
+      expect(screen.getByTestId('entities-tree')).toBeInTheDocument();
       
-      renderWithProviders();
+      // Module icons don't exist when expanded
+      const icons = screen.queryByAltText('glossary');
+      expect(icons).not.toBeInTheDocument();
+    });
+
+    it('should only open one popover at a time when switching modules', async 
() => {
+      // Find the glossary icon and click it
+      const glossaryIcon = screen.getByAltText('glossary');
+      fireEvent.click(glossaryIcon.closest('button')!);
+
+      await waitFor(() => {
+        
expect(screen.getAllByTestId('glossary-tree').length).toBeGreaterThan(0);
+      });
+
+      // Click entities icon
+      const entitiesIcon = screen.getByAltText('entities');
+      fireEvent.click(entitiesIcon.closest('button')!);
+
+      await waitFor(() => {
+        expect(screen.getAllByTestId('entities-tree')).toHaveLength(2);
+        expect(screen.getAllByTestId('glossary-tree')).toHaveLength(1);
+      });
+    });
+
+    it('should calculate popover max height correctly when near viewport 
bottom', async () => {
+      const originalInnerHeight = window.innerHeight;
+      Object.defineProperty(window, 'innerHeight', { value: 600, configurable: 
true });
+
+      const originalGetBoundingClientRect = 
Element.prototype.getBoundingClientRect;
+      Element.prototype.getBoundingClientRect = jest.fn(() => ({
+        top: 500, // Near bottom
+        bottom: 540,
+        left: 0,
+        right: 50,
+        width: 50,
+        height: 40,
+        x: 0,
+        y: 500,
+        toJSON: () => {}
+      }));
+
+      const glossaryIcon = screen.getByAltText('glossary');
+      fireEvent.click(glossaryIcon.closest('button')!);
+
+      await waitFor(() => {
+        const paper = document.querySelector('.sidebar-popover-paper') as 
HTMLElement;
+        expect(paper).toBeInTheDocument();
+        // spaceBelow = 600 - 500 - 24 = 76 (< 350, so isBottom = true)
+        // setPopoverMaxHeight = max(250, 540 - 24) = 516px
+        expect(paper.style.maxHeight).toBe('516px');
+      });
       
-      expect(screen.getByTestId('entities-tree')).toBeInTheDocument();
+      // Restore
+      Object.defineProperty(window, 'innerHeight', { value: 
originalInnerHeight, configurable: true });
+      Element.prototype.getBoundingClientRect = originalGetBoundingClientRect;
+    });
+  });
+
+  describe('Active State Markers', () => {
+    it('should apply active state markers correctly', async () => {
+      // Test Entities active (type param present but isCF is not true)
+      (global as unknown as Record<string, unknown>).mockLocation = { 
pathname: '/search', search: '?type=table' };
+      const { unmount: unmount1 } = renderWithProviders();
+      let toggleButton = 
screen.getByTestId('KeyboardDoubleArrowLeftIcon').closest('button');
+      fireEvent.click(toggleButton!);
+      
+      let entitiesIcon = screen.getByAltText('entities');
+      expect(entitiesIcon.closest('.sidebar-icon-active')).toBeInTheDocument();
+      unmount1();
+
+      // Test Custom Filters active (isCF=true)
+      (global as unknown as Record<string, unknown>).mockLocation = { 
pathname: '/search', search: '?isCF=true&type=myFilter' };
+      const { unmount: unmount2 } = renderWithProviders();
+      toggleButton = 
screen.getByTestId('KeyboardDoubleArrowLeftIcon').closest('button');
+      fireEvent.click(toggleButton!);
+      
+      let customFiltersIcon = screen.getByAltText('custom filters');
+      
expect(customFiltersIcon.closest('.sidebar-icon-active')).toBeInTheDocument();
+      
+      // Entities should NOT be active if isCF=true
+      entitiesIcon = screen.getByAltText('entities');
+      
expect(entitiesIcon.closest('.sidebar-icon-active')).not.toBeInTheDocument();
+      unmount2();
+
+      // Test Glossary active
+      (global as unknown as Record<string, unknown>).mockLocation = { 
pathname: '/glossary', search: '' };
+      const { unmount: unmount3 } = renderWithProviders();
+      toggleButton = 
screen.getByTestId('KeyboardDoubleArrowLeftIcon').closest('button');
+      fireEvent.click(toggleButton!);
+      
+      let glossaryIcon = screen.getByAltText('glossary');
+      expect(glossaryIcon.closest('.sidebar-icon-active')).toBeInTheDocument();
+      unmount3();
+
+      // Test Classification active
+      (global as unknown as Record<string, unknown>).mockLocation = { 
pathname: '/search', search: '?tag=PII' };
+      const { unmount: unmount4 } = renderWithProviders();
+      toggleButton = 
screen.getByTestId('KeyboardDoubleArrowLeftIcon').closest('button');
+      fireEvent.click(toggleButton!);
+      
+      let classificationIcon = screen.getByAltText('classifications');
+      
expect(classificationIcon.closest('.sidebar-icon-active')).toBeInTheDocument();
+      unmount4();
+
+      // Test Business Metadata active
+      (global as unknown as Record<string, unknown>).mockLocation = { 
pathname: '/administrator/businessMetadata', search: '' };
+      const { unmount: unmount5 } = renderWithProviders();
+      toggleButton = 
screen.getByTestId('KeyboardDoubleArrowLeftIcon').closest('button');
+      fireEvent.click(toggleButton!);
+      
+      let bmIcon = screen.getByAltText('business metadata');
+      expect(bmIcon.closest('.sidebar-icon-active')).toBeInTheDocument();
+      unmount5();
+
+      // Test Relationships active
+      (global as unknown as Record<string, unknown>).mockLocation = { 
pathname: '/search', search: '?relationshipName=Employee' };
+      const { unmount: unmount6 } = renderWithProviders();
+      toggleButton = 
screen.getByTestId('KeyboardDoubleArrowLeftIcon').closest('button');
+      fireEvent.click(toggleButton!);
+      
+      let relIcon = screen.getByAltText('relationships');
+      expect(relIcon.closest('.sidebar-icon-active')).toBeInTheDocument();
+      unmount6();
+
+      (global as unknown as Record<string, unknown>).mockLocation = undefined;
     });
   });
 });

Review Comment:
   Add test: on /search with no params, collapsed sidebar should have no 
.sidebar-icon-active icons.



##########
dashboard/src/redux/slice/sessionSlice.ts:
##########
@@ -17,17 +17,23 @@
 

Review Comment:
   Add test: fetchVersionData.rejected with existing data — document whether 
data should be retained or cleared.



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