mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[SecuritySolution] Display full name in greetings (#180670)
## Summary We could find the user's full name might not always be available from the 1st image below, but username should always exist. Previously, we displayed username straight away and it didn't look good. [bug](https://github.com/elastic/kibana/issues/177204) In this PR, we change the logic and display user's full name if it exists, otherwise fallback to the username. **No Full Name scenario - It displays username** <img width="2293" alt="Screenshot 2024-04-12 at 09 58 52" src="355e5a3d
-e8f8-4204-8234-8eddd14691e1"> <img width="2559" alt="Screenshot 2024-04-12 at 09 59 18" src="14ba8250
-57cf-4fc1-9bdf-a3ac021b91c8"> **Full Name available scenario - It displays the full name** <img width="2291" alt="Screenshot 2024-04-12 at 10 07 28" src="57cb5aa2
-ae23-4e0b-bd13-7b6d72edce40"> <img width="2557" alt="Screenshot 2024-04-12 at 10 08 24" src="a4cbd64f
-7eef-454b-a5fc-e12f25a82ea5"> ### Checklist Delete any items that are not applicable to this PR. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
bcd709352a
commit
01e2379929
3 changed files with 103 additions and 4 deletions
|
@ -22,6 +22,7 @@ jest.mock('../../../lib/kibana', () => {
|
|||
const original = jest.requireActual('../../../lib/kibana');
|
||||
return {
|
||||
...original,
|
||||
useCurrentUser: jest.fn().mockReturnValue({ fullName: 'UserFullName' }),
|
||||
useAppUrl: jest.fn().mockReturnValue({ getAppUrl: jest.fn().mockReturnValue('mock url') }),
|
||||
};
|
||||
});
|
||||
|
@ -63,10 +64,14 @@ describe('OnboardingComponent', () => {
|
|||
ViewAlertsSteps.viewAlerts,
|
||||
],
|
||||
};
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should render page title, subtitle, and description', () => {
|
||||
const { getByText } = render(<OnboardingComponent {...props} />);
|
||||
|
||||
const pageTitle = getByText('Hi Unknown!');
|
||||
const pageTitle = getByText('Hi UserFullName!');
|
||||
const subtitle = getByText(`Get started with Security`);
|
||||
const description = getByText(
|
||||
`This area shows you everything you need to know. Feel free to explore all content. You can always come back here at any time.`
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import { WelcomeHeader } from '.';
|
||||
import { useCurrentUser } from '../../../../lib/kibana';
|
||||
import { CurrentPlan } from './current_plan';
|
||||
import { ProductTier } from '../configs';
|
||||
import { useProjectFeaturesUrl } from '../hooks/use_project_features_url';
|
||||
|
||||
jest.mock('../../../../lib/kibana', () => ({
|
||||
useCurrentUser: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('../hooks/use_project_features_url', () => ({
|
||||
useProjectFeaturesUrl: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('./current_plan', () => ({
|
||||
CurrentPlan: jest.fn().mockReturnValue(<div data-test-subj="current-plan" />),
|
||||
}));
|
||||
|
||||
const mockUseCurrentUser = useCurrentUser as jest.Mock;
|
||||
const mockCurrentPlan = CurrentPlan as unknown as jest.Mock;
|
||||
const mockUseProjectFeaturesUrl = useProjectFeaturesUrl as jest.Mock;
|
||||
const mockProjectFeaturesUrl = '/features';
|
||||
|
||||
describe('WelcomeHeaderComponent', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should render fullName when fullName is provided', () => {
|
||||
const fullName = 'John Doe';
|
||||
mockUseCurrentUser.mockReturnValue({ fullName });
|
||||
const { getByText } = render(<WelcomeHeader />);
|
||||
const titleElement = getByText(`Hi ${fullName}!`);
|
||||
expect(titleElement).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render username when fullName is not provided', () => {
|
||||
const username = 'jd';
|
||||
mockUseCurrentUser.mockReturnValue({ username });
|
||||
|
||||
const { getByText } = render(<WelcomeHeader />);
|
||||
const titleElement = getByText(`Hi ${username}!`);
|
||||
expect(titleElement).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should not render the greeting message if both fullName and username are not available', () => {
|
||||
mockUseCurrentUser.mockReturnValue({});
|
||||
|
||||
const { queryByTestId } = render(<WelcomeHeader />);
|
||||
const greetings = queryByTestId(`welcome-header-greetings`);
|
||||
expect(greetings).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render subtitle', () => {
|
||||
const { getByText } = render(<WelcomeHeader />);
|
||||
const subtitleElement = getByText('Get started with Security');
|
||||
expect(subtitleElement).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render description', () => {
|
||||
const { getByText } = render(<WelcomeHeader />);
|
||||
const descriptionElement = getByText(
|
||||
'This area shows you everything you need to know. Feel free to explore all content. You can always come back here at any time.'
|
||||
);
|
||||
expect(descriptionElement).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render current plan', () => {
|
||||
mockUseProjectFeaturesUrl.mockReturnValue(mockProjectFeaturesUrl);
|
||||
const { getByTestId } = render(<WelcomeHeader productTier={ProductTier.complete} />);
|
||||
const currentPlanElement = getByTestId('current-plan');
|
||||
expect(currentPlanElement).toBeInTheDocument();
|
||||
expect(mockCurrentPlan.mock.calls[0][0]).toEqual({
|
||||
productTier: 'complete',
|
||||
projectFeaturesUrl: mockProjectFeaturesUrl,
|
||||
});
|
||||
});
|
||||
});
|
|
@ -22,6 +22,10 @@ import { CurrentPlan } from './current_plan';
|
|||
|
||||
const WelcomeHeaderComponent: React.FC<{ productTier?: ProductTier }> = ({ productTier }) => {
|
||||
const userName = useCurrentUser();
|
||||
|
||||
// Full name could be null, user name should always exist
|
||||
const name = userName?.fullName ?? userName?.username;
|
||||
|
||||
const projectFeaturesUrl = useProjectFeaturesUrl();
|
||||
|
||||
const {
|
||||
|
@ -38,9 +42,13 @@ const WelcomeHeaderComponent: React.FC<{ productTier?: ProductTier }> = ({ produ
|
|||
return (
|
||||
<EuiFlexGroup className={headerStyles} data-test-subj="welcome-header">
|
||||
<EuiFlexItem grow={false} className={headerContentStyles}>
|
||||
{userName?.username && (
|
||||
<EuiTitle size="l" className={headerTitleStyles}>
|
||||
<span>{GET_STARTED_PAGE_TITLE(userName.username)}</span>
|
||||
{name && (
|
||||
<EuiTitle
|
||||
size="l"
|
||||
className={headerTitleStyles}
|
||||
data-test-subj="welcome-header-greetings"
|
||||
>
|
||||
<span>{GET_STARTED_PAGE_TITLE(name)}</span>
|
||||
</EuiTitle>
|
||||
)}
|
||||
<EuiSpacer size="s" />
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue