Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { AIChatExperience } from '@kbn/ai-assistant-common';
import { createAiNavigationTree } from './ai_navigation_tree';

describe('createAiNavigationTree', () => {
it('returns the Workflows link between Agents and Value report when enabled', () => {
const navigationTree = createAiNavigationTree(AIChatExperience.Agent, true);

const primaryNavSection = navigationTree.body[4];
const children = 'children' in primaryNavSection ? primaryNavSection.children : [];

const workflowsIndex = children?.findIndex(
(item) => 'link' in item && item.link === 'workflows'
);
const agentsIndex = children?.findIndex(
(item) => 'link' in item && item.link === 'agent_builder'
);

expect(workflowsIndex).toBe((agentsIndex ?? 0) + 1);
});

it('does not include the Workflows link when disabled', () => {
const navigationTree = createAiNavigationTree(AIChatExperience.Agent, false);

const primaryNavSection = navigationTree.body[4];
const children = 'children' in primaryNavSection ? primaryNavSection.children : [];

const workflowsIndex = children?.findIndex(
(item) => 'link' in item && item.link === 'workflows'
);

expect(workflowsIndex).toBe(-1);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ const SOLUTION_NAME = i18n.translate(
);

export const createAiNavigationTree = (
chatExperience: AIChatExperience = AIChatExperience.Classic
chatExperience: AIChatExperience = AIChatExperience.Classic,
workflowsUiEnabled: boolean = false
): NavigationTreeDefinition => ({
body: [
{
Expand Down Expand Up @@ -77,7 +78,7 @@ export const createAiNavigationTree = (
breadcrumbStatus: 'hidden',
children: [
{
link: 'discover',
link: 'discover' as AppDeepLinkId,
},
...(chatExperience === AIChatExperience.Agent
? [
Expand All @@ -88,6 +89,13 @@ export const createAiNavigationTree = (
},
]
: []),
...(workflowsUiEnabled
? [
{
link: 'workflows' as AppDeepLinkId,
},
]
: []),
{
id: SecurityPageName.aiValue,
link: securityLink(SecurityPageName.aiValue),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import { of } from 'rxjs';
import { AIChatExperience } from '@kbn/ai-assistant-common';
import { WORKFLOWS_UI_SETTING_ID } from '@kbn/workflows/common/constants';
import type { ProductLine, ProductTier } from '../../common/product';
import { mockServices } from '../common/services/__mocks__/services.mock';
import { registerSolutionNavigation } from './navigation';
Expand All @@ -31,8 +32,13 @@ describe('Security Side Nav', () => {
beforeEach(() => {
jest.clearAllMocks();
initNavigationSpy.mockReset();
// Mock settings.client.get$ to return Classic chat experience by default
services.settings.client.get$ = jest.fn().mockReturnValue(of(AIChatExperience.Classic));
services.settings.client.get$ = jest.fn().mockImplementation((key: string) => {
if (key === WORKFLOWS_UI_SETTING_ID) {
return of(false);
}

return of(AIChatExperience.Classic);
});
});

it('registers the navigation tree definition for serverless security', async () => {
Expand Down Expand Up @@ -64,7 +70,7 @@ describe('Security Side Nav', () => {
]);

expect(initNavigationSpy).toHaveBeenCalled();
expect(mockedCreateAiNavigationTree).toHaveBeenCalledWith(AIChatExperience.Classic);
expect(mockedCreateAiNavigationTree).toHaveBeenCalledWith(AIChatExperience.Classic, false);
expect(mockedCreateNavigationTree).not.toHaveBeenCalled();

const [, navigationTree$] = initNavigationSpy.mock.calls[0];
Expand All @@ -77,7 +83,13 @@ describe('Security Side Nav', () => {
});

it('passes Agent chat experience when settings return Agent', async () => {
services.settings.client.get$ = jest.fn().mockReturnValue(of(AIChatExperience.Agent));
services.settings.client.get$ = jest.fn().mockImplementation((key: string) => {
if (key === WORKFLOWS_UI_SETTING_ID) {
return of(false);
}

return of(AIChatExperience.Agent);
});

await registerSolutionNavigation(services, []);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import * as Rx from 'rxjs';
import { firstValueFrom } from 'rxjs';
import { AI_CHAT_EXPERIENCE_TYPE } from '@kbn/management-settings-ids';
import { AIChatExperience } from '@kbn/ai-assistant-common';
import { ProductTier } from '../../common/product';
import { WORKFLOWS_UI_SETTING_ID } from '@kbn/workflows/common/constants';
import { ProductLine } from '../../common/product';
import type { SecurityProductTypes } from '../../common/config';
import { type Services } from '../common/services';
import { createAiNavigationTree } from './ai_navigation/ai_navigation_tree';
Expand All @@ -20,7 +21,7 @@ export const registerSolutionNavigation = async (
productTypes: SecurityProductTypes
) => {
const shouldUseAINavigation = productTypes.some(
(productType) => productType.product_tier === ProductTier.searchAiLake
(productType) => productType.product_line === ProductLine.aiSoc
);

const chatExperience$ = services.settings.client.get$<AIChatExperience>(
Expand All @@ -31,8 +32,14 @@ export const registerSolutionNavigation = async (
// Get initial chat experience for setting initial navigation tree
const initialChatExperience = await firstValueFrom(chatExperience$);

const workflowsUiEnabled$ = services.settings.client.get$<boolean>(
WORKFLOWS_UI_SETTING_ID,
false
);
const workflowsUiEnabled = await firstValueFrom(workflowsUiEnabled$);

const navigationTree = shouldUseAINavigation
? createAiNavigationTree(initialChatExperience)
? createAiNavigationTree(initialChatExperience, workflowsUiEnabled)
: await createNavigationTree(services, initialChatExperience);

services.securitySolution.setSolutionNavigationTree(navigationTree);
Expand Down
Loading