Skip to content

Conversation

@Holocraft
Copy link
Contributor

@Holocraft Holocraft commented Oct 30, 2025

Description

This change makes it so the active selection in Privilege Zones details page has the active blue border for only the currently selected item.

Motivation and Context

Resolves <BED-6625>

To be more clear of what is currently selected, we limit the active blue border for only the currently selected item instead of giving that border to every selection in the tree. The gray selected background will still be there for prior selected items so that the user can see where they are in the tree.

How Has This Been Tested?

Fixed current unit tests to adhere to the new structure. Also manually tested.

Screenshots (optional):

Screenshot 2025-10-30 at 11 16 07 AM

Types of changes

  • Chore (a change that does not modify the application functionality)
  • New feature (non-breaking change which adds functionality)

Checklist:

Summary by CodeRabbit

  • New Features

    • API version endpoint now returns product edition alongside server version.
    • Introduced unified selection highlight that shows active tag/selector/member by type.
  • Style

    • Polished privilege zones details UI: more consistent buttons, simplified click behavior, and improved list/item highlighting and layout for clearer navigation.

@Holocraft Holocraft self-assigned this Oct 30, 2025
@Holocraft Holocraft added enhancement New feature or request user interface A pull request containing changes affecting the UI code. labels Oct 30, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 30, 2025

Walkthrough

Refactors SelectedHighlight into its own component that derives active state from route params; updates consuming PrivilegeZones Details components and tests to use itemId/type-based API; removes SelectedHighlight from utils; and adds a new string field product_edition to the API version response schema in the OpenAPI spec.

Changes

Cohort / File(s) Summary
OpenAPI: VersionResponse
packages/go/openapi/doc/openapi.json
Added new product_edition string field to the API version response schema returned by GET /api/version.
New SelectedHighlight component
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.tsx, packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.test.tsx
Introduced SelectedHighlight component (props: itemId, `type: 'tag'
Utils cleanup
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/utils.tsx
Removed the previous SelectedHighlight export and related isActive helper; retained other helpers (isTag, isSelector, getSelectorSeedType, getListHeight).
PrivilegeZones Details components
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/Details.tsx, .../MembersList.tsx, .../SelectorsList.tsx, .../TagList.tsx
Updated callsites to use new SelectedHighlight(itemId, type) API; made selected prop optional in MembersListProps and TagListProps; minor handler/prop formatting, styling and class adjustments (e.g., removed fixed row height, simplified onClick).
Tests: TagList
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/TagList.test.tsx
Updated test expectations (data-testid) to align with type-based data-testid generation for items.

Sequence Diagram(s)

sequenceDiagram
    participant Route as Route / URL
    participant Hook as usePZPathParams
    participant Component as Details Component
    participant Highlight as SelectedHighlight

    Note over Route,Hook: URL params represent active tag/selector/member
    Route->>Hook: params change (tagId/selectorId/memberId)
    Hook-->>Highlight: exposes active ids
    Component->>Highlight: render with itemId + type
    Highlight->>Highlight: compare provided type+itemId to active ids
    alt match
        Highlight-->>Component: render highlight (data-testid includes type + itemId)
    else no match
        Highlight-->>Component: render nothing
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

  • Areas needing extra attention:
    • SelectedHighlight conditional logic vs. usePZPathParams contract and edge-case id coercion.
    • All consumers (MembersList, SelectorsList, TagList, Details) to ensure consistent itemId typing and type values.
    • Test updates verifying correct data-testids and mocked route params.

Possibly related PRs

Suggested reviewers

  • urangel
  • mistahj67
  • catsiller

Poem

🐰 In burrows of code I hopped with delight,
I traded props for routes in the night,
Tags, members, selectors now gleam,
Highlighted by params — a rabbit's dream,
And the API gained product_edition bright. ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The pull request title "BED-6625 make the active border only on active selection" directly addresses the primary objective of this changeset. The raw summary confirms that the main change is refactoring how the active/highlight border appears in the Privilege Zones details page, specifically limiting it to only the currently selected item rather than every selection. The title is clear, concise, and specific enough that a teammate scanning the history would understand this is about modifying the active border display behavior. The BED-6625 reference provides proper ticket tracking context.
Description Check ✅ Passed The pull request description aligns well with the required template structure. It includes all essential sections: a clear description of the changes, motivation and context with the ticket reference (BED-6625) explaining why the change improves clarity, details on testing methodology (unit test updates plus manual testing), and a supporting screenshot. The types of changes are properly selected, and the checklist is completed with all prerequisites confirmed. While the description could provide slightly more technical detail about the SelectedHighlight component refactoring, the provided information is sufficiently clear and actionable for code review purposes.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch BED-6625

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4fd958f and c44f961.

📒 Files selected for processing (6)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/MembersList.tsx (2 hunks)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.test.tsx (1 hunks)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.tsx (1 hunks)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectorsList.tsx (2 hunks)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/TagList.tsx (3 hunks)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/utils.tsx (0 hunks)
💤 Files with no reviewable changes (1)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/utils.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/TagList.tsx
🧰 Additional context used
🧠 Learnings (7)
📚 Learning: 2025-08-28T19:26:03.304Z
Learnt from: benwaples
Repo: SpecterOps/BloodHound PR: 1829
File: packages/javascript/bh-shared-ui/src/views/ZoneManagement/ZoneAnalysisIcon.tsx:26-26
Timestamp: 2025-08-28T19:26:03.304Z
Learning: In packages/javascript/bh-shared-ui/src/hooks/, useZonePathParams is exported through the useZoneParams barrel (useZoneParams/index.ts exports it via wildcard from useZonePathParams.tsx), and usePrivilegeZoneAnalysis is exported through useConfiguration.ts. Both are available via the main hooks barrel import.

Applied to files:

  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.tsx
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectorsList.tsx
📚 Learning: 2025-08-25T20:12:35.629Z
Learnt from: mistahj67
Repo: SpecterOps/BloodHound PR: 1803
File: packages/javascript/bh-shared-ui/src/views/ZoneManagement/Summary/SummaryCard.tsx:24-24
Timestamp: 2025-08-25T20:12:35.629Z
Learning: The useHighestPrivilegeTagId hook is available through the hooks barrel export in packages/javascript/bh-shared-ui/src/hooks/index.ts via the wildcard export `export * from './useAssetGroupTags'`. The import `import { useHighestPrivilegeTagId } from '../../../hooks'` works correctly and doesn't cause build failures.

Applied to files:

  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.tsx
📚 Learning: 2025-09-08T19:22:49.284Z
Learnt from: jvacca-specterops
Repo: SpecterOps/BloodHound PR: 1823
File: packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/SavedQueries/TagToZoneLabelDialog.tsx:34-35
Timestamp: 2025-09-08T19:22:49.284Z
Learning: In BloodHound's TagToZoneLabelDialog component (packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/SavedQueries/TagToZoneLabelDialog.tsx), importing AssetGroupTag type from 'js-client-library' to type tag shapes is incorrect - this type should not be used for typing tags in this context.

Applied to files:

  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.tsx
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.test.tsx
📚 Learning: 2025-08-11T23:51:32.709Z
Learnt from: benwaples
Repo: SpecterOps/BloodHound PR: 1749
File: packages/javascript/bh-shared-ui/src/hooks/useExploreSelectedItem.tsx:40-46
Timestamp: 2025-08-11T23:51:32.709Z
Learning: The useGraphItem hook in packages/javascript/bh-shared-ui/src/hooks/useGraphItem.tsx already has an enabled field set to !!itemId, which prevents the query from executing when itemId is falsy, providing built-in null-safety.

Applied to files:

  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.tsx
📚 Learning: 2025-08-11T23:51:32.709Z
Learnt from: benwaples
Repo: SpecterOps/BloodHound PR: 1749
File: packages/javascript/bh-shared-ui/src/hooks/useExploreSelectedItem.tsx:40-46
Timestamp: 2025-08-11T23:51:32.709Z
Learning: The version of react-query used in this codebase doesn't have typeguard support for itemId when used in the enabled field, so type assertions may still be necessary even with enabled checks in place.

Applied to files:

  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.tsx
📚 Learning: 2025-09-08T19:24:33.396Z
Learnt from: jvacca-specterops
Repo: SpecterOps/BloodHound PR: 1823
File: packages/javascript/bh-shared-ui/src/components/PrebuiltSearchList/PrebuiltSearchList.test.tsx:17-20
Timestamp: 2025-09-08T19:24:33.396Z
Learning: In BloodHound codebase, prefer importing `render` and `screen` from custom test-utils (e.g., `import { render, screen } from '../../test-utils';`) instead of directly from `testing-library/react`.

Applied to files:

  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.test.tsx
📚 Learning: 2025-08-27T21:15:32.207Z
Learnt from: jvacca-specterops
Repo: SpecterOps/BloodHound PR: 1823
File: packages/javascript/bh-shared-ui/src/commonSearchesAGT.ts:184-187
Timestamp: 2025-08-27T21:15:32.207Z
Learning: In the BloodHound codebase, syntax fixes for invalid Cypher patterns (like `*..` → `*1..`) may be considered out of scope for specific PRs, even when flagged during review.

Applied to files:

  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.test.tsx
🧬 Code graph analysis (4)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.tsx (1)
packages/javascript/bh-shared-ui/src/hooks/usePZParams/usePZPathParams.tsx (1)
  • usePZPathParams (20-53)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.test.tsx (1)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.tsx (1)
  • SelectedHighlight (4-30)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectorsList.tsx (2)
packages/javascript/bh-shared-ui/src/utils/theme.ts (1)
  • cn (41-43)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.tsx (1)
  • SelectedHighlight (4-30)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/MembersList.tsx (2)
packages/javascript/js-client-library/src/responses.ts (1)
  • AssetGroupTagMemberListItem (177-179)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.tsx (1)
  • SelectedHighlight (4-30)
⏰ 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). (4)
  • GitHub Check: Build BloodHound Container Image / Build and Package Container
  • GitHub Check: run-analysis
  • GitHub Check: build-ui
  • GitHub Check: run-tests
🔇 Additional comments (4)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.tsx (1)

17-28: Active-depth gating is clean.

The member→selector→tag prioritization keeps the blue bar tied to the truly active node, while the string coercion prevents number/string param mismatches. Nicely tightened.

packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectorsList.tsx (1)

113-125: Selector rows now honor the new highlight contract.

Injecting SelectedHighlight with the selector type while leaving the neutral background on the stored selected id gives the “only current item gets a border” behavior without upsetting the list layout.

packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.test.tsx (1)

17-74: Solid coverage across route permutations.

Mocking usePZPathParams to walk through tag, selector, and member states (plus negative checks) makes this highlight logic hard to regress.

packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/MembersList.tsx (1)

63-79: Members list wiring matches the shared highlight behavior.

Reusing SelectedHighlight with type='member' while keeping the neutral background logic ensures the active border follows the drill-down to members without losing the breadcrumb feel.


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

@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

Caution

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

⚠️ Outside diff range comments (1)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/Details.tsx (1)

19-204: Active highlight desync on refresh/deep link

With this state initialised from tagId only, any deep link, refresh, or browser back that lands on a selector or member route leaves the blue “active” border stuck on the tag list. That breaks the PR intent of showing the border only on the current item. Seed and keep activeItem in sync with the route params so the highlight always follows the displayed detail.

-import { FC, useContext, useState } from 'react';
+import { FC, useContext, useEffect, useState } from 'react';
@@
-    const [activeItem, setActiveItem] = useState<{ id: string; type: 'tag' | 'selector' | 'member' } | undefined>(
-        tagId ? { id: tagId, type: 'tag' } : undefined
-    );
+    const getActiveItemFromParams = () => {
+        if (memberId) return { id: String(memberId), type: 'member' as const };
+        if (selectorId) return { id: String(selectorId), type: 'selector' as const };
+        if (tagId) return { id: String(tagId), type: 'tag' as const };
+        return undefined;
+    };
+
+    const [activeItem, setActiveItem] = useState<
+        { id: string; type: 'tag' | 'selector' | 'member' } | undefined
+    >(getActiveItemFromParams);
+
+    useEffect(() => {
+        setActiveItem(getActiveItemFromParams());
+    }, [memberId, selectorId, tagId]);
🧹 Nitpick comments (1)
packages/go/openapi/doc/openapi.json (1)

3365-3370: Add description/enum and an example for product_edition to tighten the contract.

The new field is good, but it lacks allowed values and a sample. Document it as Community/Enterprise and add a 200 example for quick discovery.

Apply this diff:

@@
                         "server_version": {
                           "type": "string"
-                        },
+                        },
                         "product_edition": {
-                          "type": "string"
+                          "type": "string",
+                          "description": "Edition of the running product.",
+                          "enum": ["Community", "Enterprise"]
                         }
@@
         "responses": {
           "200": {
             "description": "OK",
             "content": {
               "application/json": {
                 "schema": {
                   "type": "object",
                   "properties": {
                     "data": {
                       "type": "object",
                       "properties": {
                         "API": {
                           "type": "object",
                           "properties": {
                             "current_version": {
                               "type": "string"
                             },
                             "deprecated_version": {
                               "type": "string"
                             }
                           }
                         },
                         "server_version": {
                           "type": "string"
                         },
                         "product_edition": {
                           "type": "string",
                           "description": "Edition of the running product.",
                           "enum": ["Community", "Enterprise"]
                         }
                       }
                     }
                   }
-                }
+                },
+                "example": {
+                  "data": {
+                    "API": {
+                      "current_version": "v2",
+                      "deprecated_version": "v1"
+                    },
+                    "server_version": "5.3.1",
+                    "product_edition": "Enterprise"
+                  }
+                }
               }
             }
           },

Please confirm the backend for GET /api/version already returns product_edition so the spec and implementation stay in sync. If helpful, I can draft an e2e check.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f79f781 and 4609a4c.

⛔ Files ignored due to path filters (1)
  • cmd/api/src/test/integration/harnesses/citrixRDPHarness.svg is excluded by !**/*.svg
📒 Files selected for processing (9)
  • packages/go/openapi/doc/openapi.json (1 hunks)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/Details.tsx (3 hunks)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/MembersList.test.tsx (1 hunks)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/MembersList.tsx (3 hunks)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectorsList.test.tsx (1 hunks)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectorsList.tsx (3 hunks)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/TagList.test.tsx (5 hunks)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/TagList.tsx (4 hunks)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/utils.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-09-08T19:22:49.284Z
Learnt from: jvacca-specterops
PR: SpecterOps/BloodHound#1823
File: packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/SavedQueries/TagToZoneLabelDialog.tsx:34-35
Timestamp: 2025-09-08T19:22:49.284Z
Learning: In BloodHound's TagToZoneLabelDialog component (packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/SavedQueries/TagToZoneLabelDialog.tsx), importing AssetGroupTag type from 'js-client-library' to type tag shapes is incorrect - this type should not be used for typing tags in this context.

Applied to files:

  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/TagList.tsx
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/utils.tsx
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/Details.tsx
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/TagList.test.tsx
📚 Learning: 2025-08-28T19:26:03.304Z
Learnt from: benwaples
PR: SpecterOps/BloodHound#1829
File: packages/javascript/bh-shared-ui/src/views/ZoneManagement/ZoneAnalysisIcon.tsx:26-26
Timestamp: 2025-08-28T19:26:03.304Z
Learning: In packages/javascript/bh-shared-ui/src/hooks/, useZonePathParams is exported through the useZoneParams barrel (useZoneParams/index.ts exports it via wildcard from useZonePathParams.tsx), and usePrivilegeZoneAnalysis is exported through useConfiguration.ts. Both are available via the main hooks barrel import.

Applied to files:

  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/utils.tsx
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/Details.tsx
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/TagList.test.tsx
📚 Learning: 2025-08-25T20:12:35.629Z
Learnt from: mistahj67
PR: SpecterOps/BloodHound#1803
File: packages/javascript/bh-shared-ui/src/views/ZoneManagement/Summary/SummaryCard.tsx:24-24
Timestamp: 2025-08-25T20:12:35.629Z
Learning: The useHighestPrivilegeTagId hook is available through the hooks barrel export in packages/javascript/bh-shared-ui/src/hooks/index.ts via the wildcard export `export * from './useAssetGroupTags'`. The import `import { useHighestPrivilegeTagId } from '../../../hooks'` works correctly and doesn't cause build failures.

Applied to files:

  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/utils.tsx
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/TagList.test.tsx
📚 Learning: 2025-08-11T23:51:32.709Z
Learnt from: benwaples
PR: SpecterOps/BloodHound#1749
File: packages/javascript/bh-shared-ui/src/hooks/useExploreSelectedItem.tsx:40-46
Timestamp: 2025-08-11T23:51:32.709Z
Learning: The version of react-query used in this codebase doesn't have typeguard support for itemId when used in the enabled field, so type assertions may still be necessary even with enabled checks in place.

Applied to files:

  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/utils.tsx
📚 Learning: 2025-08-11T23:51:32.709Z
Learnt from: benwaples
PR: SpecterOps/BloodHound#1749
File: packages/javascript/bh-shared-ui/src/hooks/useExploreSelectedItem.tsx:40-46
Timestamp: 2025-08-11T23:51:32.709Z
Learning: The useGraphItem hook in packages/javascript/bh-shared-ui/src/hooks/useGraphItem.tsx already has an enabled field set to !!itemId, which prevents the query from executing when itemId is falsy, providing built-in null-safety.

Applied to files:

  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/utils.tsx
🧬 Code graph analysis (5)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/TagList.tsx (2)
packages/javascript/bh-shared-ui/src/utils/theme.ts (1)
  • cn (41-43)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/utils.tsx (1)
  • SelectedHighlight (20-31)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/MembersList.tsx (1)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/utils.tsx (1)
  • SelectedHighlight (20-31)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/Details.tsx (4)
packages/javascript/bh-shared-ui/src/routes/index.tsx (3)
  • privilegeZonesPath (22-22)
  • detailsPath (23-23)
  • selectorsPath (19-19)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/TagList.tsx (1)
  • TagList (46-137)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectorsList.tsx (1)
  • SelectorsList (91-151)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/MembersList.tsx (1)
  • MembersList (55-116)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectorsList.tsx (1)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/utils.tsx (1)
  • SelectedHighlight (20-31)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/TagList.test.tsx (3)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/TagList.tsx (1)
  • TagList (46-137)
packages/javascript/js-client-library/src/types.ts (1)
  • AssetGroupTag (99-110)
packages/javascript/bh-shared-ui/src/routes/index.tsx (3)
  • privilegeZonesPath (22-22)
  • zonesPath (17-17)
  • detailsPath (23-23)
⏰ 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). (4)
  • GitHub Check: Build BloodHound Container Image / Build and Package Container
  • GitHub Check: run-analysis
  • GitHub Check: build-ui
  • GitHub Check: run-tests

Copy link
Contributor

@mistahj67 mistahj67 left a comment

Choose a reason for hiding this comment

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

Discussed relying on usePZPathParams instead of passing state through the various components and adding a small targeted SelectedHighlight test 🙇

@specter-flq specter-flq self-requested a review October 30, 2025 20:32
Copy link
Contributor

@specter-flq specter-flq left a comment

Choose a reason for hiding this comment

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

LGTM! Just that change that @mistahj67 caught and good to go

@specter-flq
Copy link
Contributor

(Out of scope but worth mentioning) I saw hardcoded color variables in some of the changed files ( although not in actual changes), also saw them used in other areas related to PZ. Would be good to have those as variables in our theme. If maybe they are close to an existing color then maybe change to that color for consistency if design approves. Maybe a backlog ticket.

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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4609a4c and 9c6fb84.

📒 Files selected for processing (7)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/Details.tsx (3 hunks)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/MembersList.tsx (2 hunks)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.text.tsx (1 hunks)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectorsList.tsx (1 hunks)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/TagList.test.tsx (1 hunks)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/TagList.tsx (3 hunks)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/utils.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/TagList.test.tsx
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/TagList.tsx
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/Details.tsx
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/MembersList.tsx
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectorsList.tsx
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-08-25T20:12:35.629Z
Learnt from: mistahj67
PR: SpecterOps/BloodHound#1803
File: packages/javascript/bh-shared-ui/src/views/ZoneManagement/Summary/SummaryCard.tsx:24-24
Timestamp: 2025-08-25T20:12:35.629Z
Learning: The useHighestPrivilegeTagId hook is available through the hooks barrel export in packages/javascript/bh-shared-ui/src/hooks/index.ts via the wildcard export `export * from './useAssetGroupTags'`. The import `import { useHighestPrivilegeTagId } from '../../../hooks'` works correctly and doesn't cause build failures.

Applied to files:

  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.text.tsx
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/utils.tsx
📚 Learning: 2025-08-28T19:26:03.304Z
Learnt from: benwaples
PR: SpecterOps/BloodHound#1829
File: packages/javascript/bh-shared-ui/src/views/ZoneManagement/ZoneAnalysisIcon.tsx:26-26
Timestamp: 2025-08-28T19:26:03.304Z
Learning: In packages/javascript/bh-shared-ui/src/hooks/, useZonePathParams is exported through the useZoneParams barrel (useZoneParams/index.ts exports it via wildcard from useZonePathParams.tsx), and usePrivilegeZoneAnalysis is exported through useConfiguration.ts. Both are available via the main hooks barrel import.

Applied to files:

  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.text.tsx
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/utils.tsx
📚 Learning: 2025-09-08T19:24:33.396Z
Learnt from: jvacca-specterops
PR: SpecterOps/BloodHound#1823
File: packages/javascript/bh-shared-ui/src/components/PrebuiltSearchList/PrebuiltSearchList.test.tsx:17-20
Timestamp: 2025-09-08T19:24:33.396Z
Learning: In BloodHound codebase, prefer importing `render` and `screen` from custom test-utils (e.g., `import { render, screen } from '../../test-utils';`) instead of directly from `testing-library/react`.

Applied to files:

  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.text.tsx
📚 Learning: 2025-09-08T19:22:49.284Z
Learnt from: jvacca-specterops
PR: SpecterOps/BloodHound#1823
File: packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/SavedQueries/TagToZoneLabelDialog.tsx:34-35
Timestamp: 2025-09-08T19:22:49.284Z
Learning: In BloodHound's TagToZoneLabelDialog component (packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/SavedQueries/TagToZoneLabelDialog.tsx), importing AssetGroupTag type from 'js-client-library' to type tag shapes is incorrect - this type should not be used for typing tags in this context.

Applied to files:

  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/utils.tsx
📚 Learning: 2025-08-11T23:51:32.709Z
Learnt from: benwaples
PR: SpecterOps/BloodHound#1749
File: packages/javascript/bh-shared-ui/src/hooks/useExploreSelectedItem.tsx:40-46
Timestamp: 2025-08-11T23:51:32.709Z
Learning: The useGraphItem hook in packages/javascript/bh-shared-ui/src/hooks/useGraphItem.tsx already has an enabled field set to !!itemId, which prevents the query from executing when itemId is falsy, providing built-in null-safety.

Applied to files:

  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/utils.tsx
🧬 Code graph analysis (2)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.text.tsx (1)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/utils.tsx (1)
  • SelectedHighlight (21-44)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/utils.tsx (1)
packages/javascript/bh-shared-ui/src/hooks/usePZParams/usePZPathParams.tsx (1)
  • usePZPathParams (20-53)
⏰ 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). (4)
  • GitHub Check: Build BloodHound Container Image / Build and Package Container
  • GitHub Check: run-analysis
  • GitHub Check: run-tests
  • GitHub Check: build-ui
🔇 Additional comments (1)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/utils.tsx (1)

21-44: Active highlight now keys off deepest path param

The memberId ? 'member' : selectorId ? 'selector' : 'tag' gating keeps the blue border on just the current leaf while parents stay gray, exactly what BED-6625 calls for. Nicely done.

Comment on lines 1 to 74
import { vi } from 'vitest';
import * as hooks from '../../../hooks';
import { render, screen } from '../../../test-utils';
import { SelectedHighlight } from './utils';

vi.mock('../../../hooks', () => ({
usePZPathParams: vi.fn(),
}));

const mockUsePZPathParams = hooks.usePZPathParams as unknown as ReturnType<typeof vi.fn>;

describe('SelectedHighlight', () => {
afterEach(() => {
vi.resetAllMocks();
});

it('renders highlight for the active tag', () => {
mockUsePZPathParams.mockReturnValue({
tagId: '1',
selectorId: undefined,
memberId: undefined,
});

render(<SelectedHighlight itemId='1' type='tag' />);

expect(screen.getByTestId('privilege-zones_details_tags-list_active-tags-item-1')).toBeInTheDocument();
});

it('does not render highlight for non-active tag', () => {
mockUsePZPathParams.mockReturnValue({
tagId: '2',
selectorId: undefined,
memberId: undefined,
});

render(<SelectedHighlight itemId='1' type='tag' />);

expect(screen.queryByTestId('privilege-zones_details_tags-list_active-tags-item-1')).not.toBeInTheDocument();
});

it('renders highlight only for active selector when selectorId is present', () => {
mockUsePZPathParams.mockReturnValue({
tagId: '1',
selectorId: '5',
memberId: undefined,
});

const { rerender } = render(<SelectedHighlight itemId='5' type='selector' />);
expect(
screen.getByTestId('privilege-zones_details_selectors-list_active-selectors-item-5')
).toBeInTheDocument();

rerender(<SelectedHighlight itemId='1' type='tag' />);
expect(screen.queryByTestId('privilege-zones_details_tags-list_active-tags-item-1')).not.toBeInTheDocument();
});

it('renders highlight only for active member when memberId is present', () => {
mockUsePZPathParams.mockReturnValue({
tagId: '1',
selectorId: '2',
memberId: '3',
});

const { rerender } = render(<SelectedHighlight itemId='3' type='member' />);
expect(screen.getByTestId('privilege-zones_details_members-list_active-members-item-3')).toBeInTheDocument();

rerender(<SelectedHighlight itemId='2' type='selector' />);
expect(
screen.queryByTestId('privilege-zones_details_selectors-list_active-selectors-item-2')
).not.toBeInTheDocument();

rerender(<SelectedHighlight itemId='1' type='tag' />);
expect(screen.queryByTestId('privilege-zones_details_tags-list_active-tags-item-1')).not.toBeInTheDocument();
});
Copy link
Contributor

@coderabbitai coderabbitai bot Oct 30, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Rename to SelectedHighlight.test.tsx so Vitest runs these specs

Because this file is named .text.tsx, our Vitest config (which only matches *.test.tsx/*.spec.tsx) will skip it, so the new coverage never executes. Please rename the file to .test.tsx before merging so these assertions actually run.

-// packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.text.tsx
+// packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.test.tsx

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.text.tsx
(lines 1-74): the test file is misnamed with a .text.tsx extension so Vitest
won't pick it up; rename the file to SelectedHighlight.test.tsx (update any
import paths or references if they exist) so the test runner includes and
executes these specs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixing

Copy link
Contributor

Choose a reason for hiding this comment

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

@Holocraft, thank you for addressing this! Once the file is renamed to .test.tsx, Vitest will discover and run these tests automatically. 🎯

/)/)

(-.-)
uu--uu


🧠 Learnings used
Learnt from: mistahj67
PR: SpecterOps/BloodHound#1803
File: packages/javascript/bh-shared-ui/src/views/ZoneManagement/Summary/SummaryCard.tsx:24-24
Timestamp: 2025-08-25T20:12:35.629Z
Learning: The useHighestPrivilegeTagId hook is available through the hooks barrel export in packages/javascript/bh-shared-ui/src/hooks/index.ts via the wildcard export `export * from './useAssetGroupTags'`. The import `import { useHighestPrivilegeTagId } from '../../../hooks'` works correctly and doesn't cause build failures.

Learnt from: benwaples
PR: SpecterOps/BloodHound#1829
File: packages/javascript/bh-shared-ui/src/views/ZoneManagement/ZoneAnalysisIcon.tsx:26-26
Timestamp: 2025-08-28T19:26:03.304Z
Learning: In packages/javascript/bh-shared-ui/src/hooks/, useZonePathParams is exported through the useZoneParams barrel (useZoneParams/index.ts exports it via wildcard from useZonePathParams.tsx), and usePrivilegeZoneAnalysis is exported through useConfiguration.ts. Both are available via the main hooks barrel import.

Learnt from: jvacca-specterops
PR: SpecterOps/BloodHound#1823
File: packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/SavedQueries/TagToZoneLabelDialog.tsx:34-35
Timestamp: 2025-09-08T19:22:49.284Z
Learning: In BloodHound's TagToZoneLabelDialog component (packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/SavedQueries/TagToZoneLabelDialog.tsx), importing AssetGroupTag type from 'js-client-library' to type tag shapes is incorrect - this type should not be used for typing tags in this context.

If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

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 (2)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.test.tsx (2)

1-15: LGTM! Clean test setup with proper imports and mocking.

The mock setup follows vitest patterns correctly and uses custom test-utils as recommended. The afterEach cleanup ensures test isolation.

Optional: Consider simpler type casting for the mock.

The type casting on line 10 works but is verbose. If desired, you could simplify to:

-const mockUsePZPathParams = hooks.usePZPathParams as unknown as ReturnType<typeof vi.fn>;
+const mockUsePZPathParams = vi.mocked(hooks.usePZPathParams);

This assumes vi.mocked is available in your vitest version and provides better type inference.


41-74: LGTM! Excellent coverage of the activation priority hierarchy.

These tests correctly verify that:

  • When selectorId is present, only selectors are highlighted (not tags)
  • When memberId is present, only members are highlighted (not selectors or tags)

The use of rerender efficiently tests multiple scenarios while maintaining clear assertions.

Recommended: Add test coverage for the "nothing selected" edge case.

Consider adding a test case where all path params are undefined to explicitly verify the component returns null when nothing is selected:

it('does not render highlight when no path params are present', () => {
    mockUsePZPathParams.mockReturnValue({
        tagId: undefined,
        selectorId: undefined,
        memberId: undefined,
    });

    render(<SelectedHighlight itemId='1' type='tag' />);

    expect(screen.queryByTestId('privilege-zones_details_tags-list_active-tags-item-1')).not.toBeInTheDocument();
});

This makes the edge case behavior explicit and improves test documentation.

Optional: Consider testing with numeric itemId values.

The component accepts itemId: string | number, but all tests use string IDs. While the component converts to string internally, testing with a numeric ID would verify the type conversion works correctly:

it('renders highlight for active tag with numeric itemId', () => {
    mockUsePZPathParams.mockReturnValue({
        tagId: '42',
        selectorId: undefined,
        memberId: undefined,
    });

    render(<SelectedHighlight itemId={42} type='tag' />);

    expect(screen.getByTestId('privilege-zones_details_tags-list_active-tags-item-42')).toBeInTheDocument();
});
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9c6fb84 and 4fd958f.

📒 Files selected for processing (1)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.test.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-08-25T20:12:35.629Z
Learnt from: mistahj67
PR: SpecterOps/BloodHound#1803
File: packages/javascript/bh-shared-ui/src/views/ZoneManagement/Summary/SummaryCard.tsx:24-24
Timestamp: 2025-08-25T20:12:35.629Z
Learning: The useHighestPrivilegeTagId hook is available through the hooks barrel export in packages/javascript/bh-shared-ui/src/hooks/index.ts via the wildcard export `export * from './useAssetGroupTags'`. The import `import { useHighestPrivilegeTagId } from '../../../hooks'` works correctly and doesn't cause build failures.

Applied to files:

  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.test.tsx
📚 Learning: 2025-09-08T19:24:33.396Z
Learnt from: jvacca-specterops
PR: SpecterOps/BloodHound#1823
File: packages/javascript/bh-shared-ui/src/components/PrebuiltSearchList/PrebuiltSearchList.test.tsx:17-20
Timestamp: 2025-09-08T19:24:33.396Z
Learning: In BloodHound codebase, prefer importing `render` and `screen` from custom test-utils (e.g., `import { render, screen } from '../../test-utils';`) instead of directly from `testing-library/react`.

Applied to files:

  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.test.tsx
📚 Learning: 2025-09-08T19:22:49.284Z
Learnt from: jvacca-specterops
PR: SpecterOps/BloodHound#1823
File: packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/SavedQueries/TagToZoneLabelDialog.tsx:34-35
Timestamp: 2025-09-08T19:22:49.284Z
Learning: In BloodHound's TagToZoneLabelDialog component (packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/SavedQueries/TagToZoneLabelDialog.tsx), importing AssetGroupTag type from 'js-client-library' to type tag shapes is incorrect - this type should not be used for typing tags in this context.

Applied to files:

  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.test.tsx
📚 Learning: 2025-08-27T21:15:32.207Z
Learnt from: jvacca-specterops
PR: SpecterOps/BloodHound#1823
File: packages/javascript/bh-shared-ui/src/commonSearchesAGT.ts:184-187
Timestamp: 2025-08-27T21:15:32.207Z
Learning: In the BloodHound codebase, syntax fixes for invalid Cypher patterns (like `*..` → `*1..`) may be considered out of scope for specific PRs, even when flagged during review.

Applied to files:

  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.test.tsx
🧬 Code graph analysis (1)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.test.tsx (1)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/utils.tsx (1)
  • SelectedHighlight (21-44)
⏰ 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). (5)
  • GitHub Check: Build BloodHound Container Image / Build and Package Container
  • GitHub Check: run-analysis
  • GitHub Check: run-go-unit-tests
  • GitHub Check: build-ui
  • GitHub Check: run-tests
🔇 Additional comments (1)
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedHighlight.test.tsx (1)

17-39: LGTM! Clear positive and negative test cases for tag activation.

These tests properly verify that the highlight appears only when the tagId matches the itemId, which is the core behavior for tag selection.

Copy link
Contributor

@mistahj67 mistahj67 left a comment

Choose a reason for hiding this comment

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

Thanks for adding those tests! Code is looking solid! I had just 2 small polish requests and I think this is ready to rock!

Copy link
Contributor

@mistahj67 mistahj67 left a comment

Choose a reason for hiding this comment

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

Code LGTM and works locally, thanks for your patience with my feedback. 🚀

@Holocraft Holocraft merged commit fea0e8a into main Oct 30, 2025
9 checks passed
@Holocraft Holocraft deleted the BED-6625 branch October 30, 2025 23:37
@github-actions github-actions bot locked and limited conversation to collaborators Oct 30, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

enhancement New feature or request user interface A pull request containing changes affecting the UI code.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants