diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_header/get_anonymization_tooltip/index.test.ts b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_header/get_anonymization_tooltip/index.test.ts new file mode 100644 index 0000000000000..35bc314abc813 --- /dev/null +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_header/get_anonymization_tooltip/index.test.ts @@ -0,0 +1,42 @@ +/* + * 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 { getAnonymizationTooltip } from '.'; +import { + SHOW_ANONYMIZED, + SHOW_REAL_VALUES, + THIS_CONVERSATION_DOES_NOT_INCLUDE_ANONYMIZED_FIELDS, +} from '../translations'; + +describe('getAnonymizationTooltip', () => { + it('returns the expected tooltip when conversationHasReplacements is false', () => { + const result = getAnonymizationTooltip({ + conversationHasReplacements: false, // <-- false + showAnonymizedValuesChecked: false, + }); + + expect(result).toBe(THIS_CONVERSATION_DOES_NOT_INCLUDE_ANONYMIZED_FIELDS); + }); + + it('returns SHOW_REAL_VALUES when showAnonymizedValuesChecked is true', () => { + const result = getAnonymizationTooltip({ + conversationHasReplacements: true, + showAnonymizedValuesChecked: true, // <-- true + }); + + expect(result).toBe(SHOW_REAL_VALUES); + }); + + it('returns SHOW_ANONYMIZED when showAnonymizedValuesChecked is false', () => { + const result = getAnonymizationTooltip({ + conversationHasReplacements: true, + showAnonymizedValuesChecked: false, // <-- false + }); + + expect(result).toBe(SHOW_ANONYMIZED); + }); +}); diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_header/get_anonymization_tooltip/index.ts b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_header/get_anonymization_tooltip/index.ts new file mode 100644 index 0000000000000..6534c6f8b0302 --- /dev/null +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_header/get_anonymization_tooltip/index.ts @@ -0,0 +1,22 @@ +/* + * 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 * as i18n from '../translations'; + +export const getAnonymizationTooltip = ({ + conversationHasReplacements, + showAnonymizedValuesChecked, +}: { + conversationHasReplacements: boolean; + showAnonymizedValuesChecked: boolean; +}): string => { + if (!conversationHasReplacements) { + return i18n.THIS_CONVERSATION_DOES_NOT_INCLUDE_ANONYMIZED_FIELDS; + } + + return showAnonymizedValuesChecked ? i18n.SHOW_REAL_VALUES : i18n.SHOW_ANONYMIZED; +}; diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_header/index.test.tsx b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_header/index.test.tsx index fa358b26c2c3a..f91de230f7fb3 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_header/index.test.tsx +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_header/index.test.tsx @@ -6,12 +6,20 @@ */ import React from 'react'; -import { act, fireEvent, render } from '@testing-library/react'; +import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'; +import userEvent, { PointerEventsCheckLevel } from '@testing-library/user-event'; + import { AssistantHeader } from '.'; import { TestProviders } from '../../mock/test_providers/test_providers'; import { alertConvo, emptyWelcomeConvo, welcomeConvo } from '../../mock/conversation'; import { useLoadConnectors } from '../../connectorland/use_load_connectors'; import { mockConnectors } from '../../mock/connectors'; +import { + CLOSE, + SHOW_ANONYMIZED, + SHOW_REAL_VALUES, + THIS_CONVERSATION_DOES_NOT_INCLUDE_ANONYMIZED_FIELDS, +} from './translations'; const onConversationSelected = jest.fn(); const mockConversations = { @@ -139,4 +147,103 @@ describe('AssistantHeader', () => { cTitle: alertConvo.title, }); }); + + it('renders an accessible close button icon', () => { + const onCloseFlyout = jest.fn(); // required to render the close button + + render(, { + wrapper: TestProviders, + }); + + expect(screen.getByRole('button', { name: CLOSE })).toBeInTheDocument(); + }); + + it('disables the anonymization toggle button when there are NO replacements', () => { + render( + , + { + wrapper: TestProviders, + } + ); + + expect(screen.getByTestId('showAnonymizedValues')).toBeDisabled(); + }); + + it('displays the expected anonymization toggle button tooltip when there are NO replacements', async () => { + render( + , + { + wrapper: TestProviders, + } + ); + + await userEvent.hover(screen.getByTestId('showAnonymizedValues'), { + pointerEventsCheck: PointerEventsCheckLevel.Never, + }); + + await waitFor(() => { + expect(screen.getByTestId('showAnonymizedValuesTooltip')).toHaveTextContent( + THIS_CONVERSATION_DOES_NOT_INCLUDE_ANONYMIZED_FIELDS + ); + }); + }); + + it('enables the anonymization toggle button when there are replacements', () => { + render( + , // <-- conversation with replacements + { + wrapper: TestProviders, + } + ); + + expect(screen.getByTestId('showAnonymizedValues')).toBeEnabled(); + }); + + it('displays the SHOW_ANONYMIZED toggle button tooltip when there are replacements and showAnonymizedValues is false', async () => { + render( + , + { + wrapper: TestProviders, + } + ); + + await userEvent.hover(screen.getByTestId('showAnonymizedValues'), { + pointerEventsCheck: PointerEventsCheckLevel.Never, + }); + + await waitFor(() => { + expect(screen.getByTestId('showAnonymizedValuesTooltip')).toHaveTextContent(SHOW_ANONYMIZED); + }); + }); + + it('displays the SHOW_REAL_VALUES toggle button tooltip when there are replacements and showAnonymizedValues is true', async () => { + render( + , + { + wrapper: TestProviders, + } + ); + + await userEvent.hover(screen.getByTestId('showAnonymizedValues'), { + pointerEventsCheck: PointerEventsCheckLevel.Never, + }); + + await waitFor(() => { + expect(screen.getByTestId('showAnonymizedValuesTooltip')).toHaveTextContent(SHOW_REAL_VALUES); + }); + }); }); diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_header/index.tsx b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_header/index.tsx index e604fb142073c..596e62e66ce5e 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_header/index.tsx +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_header/index.tsx @@ -26,6 +26,7 @@ import { FlyoutNavigation } from '../assistant_overlay/flyout_navigation'; import { AssistantSettingsModal } from '../settings/assistant_settings_modal'; import * as i18n from './translations'; import { AIConnector } from '../../connectorland/connector_selector'; +import { getAnonymizationTooltip } from './get_anonymization_tooltip'; import { SettingsContextMenu } from '../settings/settings_context_menu/settings_context_menu'; interface OwnProps { @@ -104,6 +105,12 @@ export const AssistantHeader: React.FC = ({ [onConversationSelected] ); + const conversationHasReplacements = !isEmpty(selectedConversation?.replacements); + const anonymizationTooltip = getAnonymizationTooltip({ + conversationHasReplacements, + showAnonymizedValuesChecked, + }); + return ( <> = ({ {onCloseFlyout && ( = ({ = ({ display="base" data-test-subj="showAnonymizedValues" isSelected={showAnonymizedValuesChecked} - aria-label={ - showAnonymizedValuesChecked ? i18n.SHOW_ANONYMIZED : i18n.SHOW_REAL_VALUES - } + aria-label={anonymizationTooltip} iconType={showAnonymizedValuesChecked ? 'eye' : 'eyeClosed'} onClick={onToggleShowAnonymizedValues} - isDisabled={isEmpty(selectedConversation?.replacements)} + disabled={!conversationHasReplacements} /> diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_header/translations.ts b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_header/translations.ts index e4f23e0970eb0..7d105e1ee69a6 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_header/translations.ts +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/assistant_header/translations.ts @@ -21,6 +21,13 @@ export const ANONYMIZATION = i18n.translate( } ); +export const CLOSE = i18n.translate( + 'xpack.elasticAssistant.assistant.assistantHeader.closeButtonLabel', + { + defaultMessage: 'Close', + } +); + export const KNOWLEDGE_BASE = i18n.translate( 'xpack.elasticAssistant.assistant.settings.knowledgeBase', { @@ -56,6 +63,13 @@ export const SHOW_REAL_VALUES = i18n.translate( } ); +export const THIS_CONVERSATION_DOES_NOT_INCLUDE_ANONYMIZED_FIELDS = i18n.translate( + 'xpack.elasticAssistant.assistant.settings.thisConversationDoesNotIncludeAnonymizedFieldsTooltip', + { + defaultMessage: 'This conversation does not include anonymized fields', + } +); + export const CANCEL_BUTTON_TEXT = i18n.translate( 'xpack.elasticAssistant.assistant.resetConversationModal.cancelButtonText', { diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/settings_context_menu/settings_context_menu.test.tsx b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/settings_context_menu/settings_context_menu.test.tsx new file mode 100644 index 0000000000000..c43869474bd17 --- /dev/null +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/settings_context_menu/settings_context_menu.test.tsx @@ -0,0 +1,25 @@ +/* + * 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 { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { TestProviders } from '../../../mock/test_providers/test_providers'; +import { SettingsContextMenu } from './settings_context_menu'; +import { AI_ASSISTANT_MENU } from './translations'; + +describe('SettingsContextMenu', () => { + it('renders an accessible menu button icon', () => { + render( + + + + ); + + expect(screen.getByRole('button', { name: AI_ASSISTANT_MENU })).toBeInTheDocument(); + }); +}); diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/settings_context_menu/settings_context_menu.tsx b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/settings_context_menu/settings_context_menu.tsx index f3bd4e372658c..5d145b6ada081 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/settings_context_menu/settings_context_menu.tsx +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/settings_context_menu/settings_context_menu.tsx @@ -24,6 +24,7 @@ import { useAssistantContext } from '../../../..'; import * as i18n from '../../assistant_header/translations'; import { AlertsSettingsModal } from '../alerts_settings/alerts_settings_modal'; import { KNOWLEDGE_BASE_TAB } from '../const'; +import { AI_ASSISTANT_MENU } from './translations'; interface Params { isDisabled?: boolean; @@ -170,7 +171,7 @@ export const SettingsContextMenu: React.FC = React.memo( button={