From 8678bd2d2961f77d0596f3ab41300446295445eb Mon Sep 17 00:00:00 2001 From: Ulises Rangel Date: Wed, 1 Jul 2026 11:55:48 -0500 Subject: [PATCH] refactor: useFetchEntityInfo uses new getNodeByID endpoint BED-8742 --- .../EntityInfo/EntityInfoContent.test.tsx | 13 ++--- .../useFetchEntityInfo.test.tsx | 37 +++---------- .../useFetchEntityInfo/useFetchEntityInfo.tsx | 53 +++++++------------ .../src/utils/entityInfoDisplay.ts | 2 - .../SelectedDetailsTabContent.test.tsx | 11 ++-- 5 files changed, 36 insertions(+), 80 deletions(-) diff --git a/packages/javascript/bh-shared-ui/src/components/EntityInfo/EntityInfoContent.test.tsx b/packages/javascript/bh-shared-ui/src/components/EntityInfo/EntityInfoContent.test.tsx index edae3c0f89cd..9d454a8c0767 100644 --- a/packages/javascript/bh-shared-ui/src/components/EntityInfo/EntityInfoContent.test.tsx +++ b/packages/javascript/bh-shared-ui/src/components/EntityInfo/EntityInfoContent.test.tsx @@ -45,16 +45,13 @@ const server = setupServer( }) ); }), - rest.post('/api/v2/graphs/cypher', (req, res, ctx) => { + rest.get('/api/v2/nodes/:id', (req, res, ctx) => { return res( ctx.json({ data: { - nodes: { - '42': { - kind: 'Unknown', - properties: { objectid: 'unknown kind' }, - }, - }, + node_id: 42, + kinds: [{ node_kind_id: 1, name: 'Unknown' }], + properties: { objectid: 'unknown kind' }, }, }) ); @@ -135,7 +132,7 @@ describe('EntityObjectInformation', () => { expect(await screen.findByText('test')).toBeInTheDocument(); }); - it('Calls the cypher search endpoint for a node with a type that is not in our schema', async () => { + it('Calls the get node by id endpoint for a node with a type that is not in our schema', async () => { const testId = '1'; const nodeType = 'Unknown'; const databaseId = '42'; diff --git a/packages/javascript/bh-shared-ui/src/hooks/useFetchEntityInfo/useFetchEntityInfo.test.tsx b/packages/javascript/bh-shared-ui/src/hooks/useFetchEntityInfo/useFetchEntityInfo.test.tsx index cb138c2e8744..dc1322df123f 100644 --- a/packages/javascript/bh-shared-ui/src/hooks/useFetchEntityInfo/useFetchEntityInfo.test.tsx +++ b/packages/javascript/bh-shared-ui/src/hooks/useFetchEntityInfo/useFetchEntityInfo.test.tsx @@ -37,16 +37,13 @@ vi.mock('../../utils/content', () => ({ vi.mock('../../utils/api', () => ({ apiClient: { - cypherSearch: vi.fn(() => + getNodeByID: vi.fn(() => Promise.resolve({ data: { data: { - nodes: { - '1': { - kinds: ['Admin_Tier_0'], - properties: mockEntityProperties, - }, - }, + node_id: 1, + kinds: [{ node_kind_id: 1, name: 'Admin_Tier_0' }], + properties: mockEntityProperties, }, }, }) @@ -68,24 +65,6 @@ const entityObjectIdRequest = () => ) ); -const entityGraphIdRequest = () => - rest.post(`/api/v2/graphs/cypher`, async (_req, res, ctx) => - res( - ctx.json({ - data: { - data: { - nodes: { - '1': { - kinds: ['Admin_Tier_0'], - properties: mockEntityProperties, - }, - }, - }, - }, - }) - ) - ); - const EntityNodeType = 'User' as const; const EntityApiPathType = 'users' as const; const EntityGraphId = '5223' as const; @@ -106,7 +85,7 @@ const mockEntityProperties = { }; describe('useFetchEntityInfo', () => { - const server = setupServer(entityObjectIdRequest(), entityGraphIdRequest()); + const server = setupServer(entityObjectIdRequest()); beforeAll(() => server.listen()); afterEach(() => server.resetHandlers()); @@ -150,7 +129,7 @@ describe('useFetchEntityInfo', () => { }); it('fetches new information when a different databaseId is passed', async () => { - const cypherSearchSpy = vi.spyOn(apiClient, 'cypherSearch'); + const getNodeByIDSpy = vi.spyOn(apiClient, 'getNodeByID'); const { result, rerender } = renderHook( (params) => useFetchEntityInfo(params), @@ -163,12 +142,12 @@ describe('useFetchEntityInfo', () => { expect(result.current.isSuccess).toBe(true); }); - expect(cypherSearchSpy).toHaveBeenCalledTimes(1); + expect(getNodeByIDSpy).toHaveBeenCalledTimes(1); rerender({ ...initialPropsCustom, databaseId: '7' }); await waitFor(() => { - expect(cypherSearchSpy).toHaveBeenCalledTimes(2); + expect(getNodeByIDSpy).toHaveBeenCalledTimes(2); }); }); }); diff --git a/packages/javascript/bh-shared-ui/src/hooks/useFetchEntityInfo/useFetchEntityInfo.tsx b/packages/javascript/bh-shared-ui/src/hooks/useFetchEntityInfo/useFetchEntityInfo.tsx index 6c93e99d2836..f6630d154f17 100644 --- a/packages/javascript/bh-shared-ui/src/hooks/useFetchEntityInfo/useFetchEntityInfo.tsx +++ b/packages/javascript/bh-shared-ui/src/hooks/useFetchEntityInfo/useFetchEntityInfo.tsx @@ -18,7 +18,6 @@ import { RequestOptions } from 'js-client-library'; import { useQuery, UseQueryResult } from 'react-query'; import { apiClient } from '../../utils/api'; import { entityInformationEndpoints } from '../../utils/content'; -import { getNodeByDatabaseIdCypher } from '../../utils/entityInfoDisplay'; import { validateNodeType } from './utils'; export type FetchEntityInfoParams = { @@ -46,48 +45,34 @@ export const useFetchEntityInfo: (param: FetchEntityInfoParams) => FetchEntityIn nodeType, databaseId, }) => { - const requestDetails: { - endpoint: ( - params: string, - options?: RequestOptions, - includeProperties?: boolean - ) => Promise>; - param: string; - } = { - endpoint: async function () { - return {}; - }, - param: '', - }; - const validatedKind = validateNodeType(nodeType); - if (validatedKind) { - requestDetails.endpoint = entityInformationEndpoints[validatedKind]; - requestDetails.param = objectId; - } else if (databaseId) { - requestDetails.endpoint = apiClient.cypherSearch; - requestDetails.param = getNodeByDatabaseIdCypher(databaseId); - } - - const informationAvailable = !!validatedKind || !!databaseId; + const informationAvailable = !!databaseId || !!validatedKind; return { ...useQuery( [FetchEntityCacheId, nodeType, objectId, databaseId], - ({ signal }) => - requestDetails.endpoint(requestDetails.param, { signal }, true).then((res) => { - if (validatedKind) { + ({ signal }) => { + if (databaseId) { + return apiClient.getNodeByID(Number(databaseId), { signal }).then((res) => { + const kinds = res.data.data.kinds.map((kind) => kind.name); + const properties = res.data.data.properties; + return { kinds, properties }; + }); + } else if (validatedKind) { + const endpoint = entityInformationEndpoints[validatedKind] as ( + params: string, + options?: RequestOptions, + includeProperties?: boolean + ) => Promise>; + return endpoint(objectId, { signal }, true).then((res) => { const kinds = res.data.data.kinds; const properties = res.data.data.props; return { kinds, properties }; - } else if (databaseId) { - const data = Object.values(res.data.data.nodes as Record)[0]; - const kinds = data.kinds; - const properties = data.properties; - return { kinds, properties }; - } else return { kinds: [], properties: {} }; - }), + }); + } + return Promise.resolve({ kinds: [], properties: {} }); + }, { refetchOnWindowFocus: false, retry: false, diff --git a/packages/javascript/bh-shared-ui/src/utils/entityInfoDisplay.ts b/packages/javascript/bh-shared-ui/src/utils/entityInfoDisplay.ts index 5072cd7ca33d..beb7a4570fa9 100644 --- a/packages/javascript/bh-shared-ui/src/utils/entityInfoDisplay.ts +++ b/packages/javascript/bh-shared-ui/src/utils/entityInfoDisplay.ts @@ -200,8 +200,6 @@ export const getEntityName = (selectedEntity: SelectedNode | null | undefined) = return name; }; -export const getNodeByDatabaseIdCypher = (id: string): string => `MATCH (n) WHERE ID(n) = ${id} RETURN n LIMIT 1`; - // Map containing all properties that should display as bitwise integers in the entity panel. // The key is the property string, the value is the amount of significant digits the hex value should display with. const BitwiseInts = new Map([['certificatemappingmethodsraw', 2]]); diff --git a/packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedDetailsTabs/SelectedDetailsTabContent.test.tsx b/packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedDetailsTabs/SelectedDetailsTabContent.test.tsx index abd9c36cdd1c..748be4736f2b 100644 --- a/packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedDetailsTabs/SelectedDetailsTabContent.test.tsx +++ b/packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Details/SelectedDetailsTabs/SelectedDetailsTabContent.test.tsx @@ -87,16 +87,13 @@ describe('Selected Details Tab Content', () => { }) ); }), - rest.post('/api/v2/graphs/cypher', async (_req, res, ctx) => { + rest.get('/api/v2/nodes/:id', async (_req, res, ctx) => { return res( ctx.json({ data: { - nodes: { - '123': { - properties: { - customprop: 'OpenGraph Value', - }, - }, + kinds: [{ name: 'Custom' }], + properties: { + customprop: 'OpenGraph Value', }, }, })