diff --git a/src/core/public/chrome/ui/header/nav_link.test.tsx b/src/core/public/chrome/ui/header/nav_link.test.tsx new file mode 100644 index 000000000000..a89bdc01d5bb --- /dev/null +++ b/src/core/public/chrome/ui/header/nav_link.test.tsx @@ -0,0 +1,63 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { isActiveNavLink, createEuiListItem } from './nav_link'; +import { ChromeNavLink } from '../../..'; +import { httpServiceMock } from '../../../http/http_service.mock'; + +describe('isActiveNavLink', () => { + it('should return true if the appId is "discover" and linkId is "discover"', () => { + expect(isActiveNavLink('discover', 'discover')).toBe(true); + }); + + it('should return true if the appId is "data-explorer" and linkId is "data-explorer"', () => { + expect(isActiveNavLink('data-explorer', 'data-explorer')).toBe(true); + }); + + it('should return true if the appId is "data-explorer" and linkId is "discover"', () => { + expect(isActiveNavLink('data-explorer', 'discover')).toBe(true); + }); + + it('should return false if the appId and linkId do not match', () => { + expect(isActiveNavLink('dashboard', 'discover')).toBe(false); + }); +}); + +const mockBasePath = httpServiceMock.createSetupContract({ basePath: '/test' }).basePath; + +describe('createEuiListItem', () => { + const mockLink: Partial = { + href: 'test', + id: 'test', + title: 'Test App', + disabled: false, + euiIconType: 'inputOutput', + icon: 'testIcon', + tooltip: 'Test App Tooltip', + }; + + const mockProps = { + link: mockLink as ChromeNavLink, + appId: 'test', + basePath: mockBasePath, + dataTestSubj: 'test-subj', + onClick: jest.fn(), + navigateToApp: jest.fn(), + externalLink: false, + }; + + it('creates a list item with the correct properties', () => { + const listItem = createEuiListItem(mockProps); + expect(listItem).toHaveProperty('label', mockProps.link.tooltip); + expect(listItem).toHaveProperty('href', mockProps.link.href); + expect(listItem).toHaveProperty('data-test-subj', mockProps.dataTestSubj); + expect(listItem).toHaveProperty('onClick'); + expect(listItem).toHaveProperty( + 'isActive', + isActiveNavLink(mockProps.appId, mockProps.link.id) + ); + expect(listItem).toHaveProperty('isDisabled', mockProps.link.disabled); + }); +}); diff --git a/src/core/public/chrome/ui/header/nav_link.tsx b/src/core/public/chrome/ui/header/nav_link.tsx index 11ff0b472bd0..38d31dbc09c9 100644 --- a/src/core/public/chrome/ui/header/nav_link.tsx +++ b/src/core/public/chrome/ui/header/nav_link.tsx @@ -39,6 +39,14 @@ import { relativeToAbsolute } from '../../nav_links/to_nav_link'; export const isModifiedOrPrevented = (event: React.MouseEvent) => event.metaKey || event.altKey || event.ctrlKey || event.shiftKey || event.defaultPrevented; +// TODO: replace hard-coded values with a registration function, so that apps can control active nav links similar to breadcrumbs +const aliasedApps: { [key: string]: string[] } = { + discover: ['data-explorer'], +}; + +export const isActiveNavLink = (appId: string | undefined, linkId: string): boolean => + !!(appId === linkId || aliasedApps[linkId]?.includes(appId || '')); + interface Props { link: ChromeNavLink; appId?: string; @@ -82,7 +90,7 @@ export function createEuiListItem({ navigateToApp(id); } }, - isActive: appId === id, + isActive: isActiveNavLink(appId, id), isDisabled: disabled, 'data-test-subj': dataTestSubj, ...(basePath && {