Skip to content

Commit

Permalink
Merge pull request elastic#8 from angorayc/onboarding-fleet-integration
Browse files Browse the repository at this point in the history
Onboarding fleet integration
  • Loading branch information
semd authored Oct 10, 2024
2 parents 794946c + cfd190c commit b16a1f7
Show file tree
Hide file tree
Showing 55 changed files with 2,262 additions and 75 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* 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, screen } from '@testing-library/react';

import { installationStatuses } from '../../../../../../common/constants';

import {
InstallationStatus,
getLineClampStyles,
shouldShowInstallationStatus,
} from './installation_status';

// Mock useEuiTheme to return a mock theme
jest.mock('@elastic/eui', () => ({
...jest.requireActual('@elastic/eui'),
useEuiTheme: () => ({
euiTheme: {
border: { radius: { medium: '4px' } },
size: { s: '8px', m: '16px' },
colors: { emptyShade: '#FFFFFF' },
},
}),
}));

describe('getLineClampStyles', () => {
it('returns the correct styles when lineClamp is provided', () => {
expect(getLineClampStyles(3)).toEqual(
'-webkit-line-clamp: 3;display: -webkit-box;-webkit-box-orient: vertical;overflow: hidden;'
);
});

it('returns an empty string when lineClamp is not provided', () => {
expect(getLineClampStyles()).toEqual('');
});
});

describe('shouldShowInstallationStatus', () => {
it('returns false when showInstallationStatus is false', () => {
expect(
shouldShowInstallationStatus({
installStatus: installationStatuses.Installed,
showInstallationStatus: false,
})
).toEqual(false);
});

it('returns true when showInstallationStatus is true and installStatus is installed', () => {
expect(
shouldShowInstallationStatus({
installStatus: installationStatuses.Installed,
showInstallationStatus: true,
})
).toEqual(true);
});

it('returns true when showInstallationStatus is true and installStatus is installFailed', () => {
expect(
shouldShowInstallationStatus({
installStatus: installationStatuses.InstallFailed,
showInstallationStatus: true,
})
).toEqual(true);
});
});

describe('InstallationStatus', () => {
it('renders null when showInstallationStatus is false', () => {
const { container } = render(
<InstallationStatus
installStatus={installationStatuses.Installed}
showInstallationStatus={false}
/>
);
expect(container.firstChild).toBeNull();
});

it('renders the Installed status correctly', () => {
render(
<InstallationStatus
installStatus={installationStatuses.Installed}
showInstallationStatus={true}
/>
);
expect(screen.getByText('Installed')).toBeInTheDocument();
});

it('renders the Install Failed status correctly', () => {
render(
<InstallationStatus
installStatus={installationStatuses.InstallFailed}
showInstallationStatus={true}
/>
);
expect(screen.getByText('Installed')).toBeInTheDocument();
});

it('renders null when installStatus is null or undefined', () => {
const { container } = render(
<InstallationStatus installStatus={null} showInstallationStatus={true} />
);
expect(container.firstChild).toBeNull();

const { container: undefinedContainer } = render(
<InstallationStatus installStatus={undefined} showInstallationStatus={true} />
);
expect(undefinedContainer.firstChild).toBeNull();
});

it('applies the correct styles for the component', () => {
const { getByTestId } = render(
<InstallationStatus
installStatus={installationStatuses.Installed}
showInstallationStatus={true}
/>
);

const spacer = getByTestId('installation-status-spacer');
const callout = getByTestId('installation-status-callout');

expect(spacer).toHaveStyle('background: #FFFFFF');
expect(callout).toHaveStyle('padding: 8px 16px');
expect(callout).toHaveTextContent('Installed');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* 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 { EuiCallOut, EuiSpacer, useEuiTheme } from '@elastic/eui';
import { i18n } from '@kbn/i18n';

import { css } from '@emotion/react';

import { installationStatuses } from '../../../../../../common/constants';
import type { EpmPackageInstallStatus } from '../../../../../../common/types';

const installedLabel = i18n.translate('xpack.fleet.packageCard.installedLabel', {
defaultMessage: 'Installed',
});

const installStatusMapToColor: Readonly<
Record<string, { color: 'success' | 'warning'; iconType: string; title: string }>
> = {
installed: {
color: 'success',
iconType: 'check',
title: installedLabel,
},
install_failed: {
color: 'warning',
iconType: 'warning',
title: installedLabel,
},
};

interface InstallationStatusProps {
installStatus: EpmPackageInstallStatus | null | undefined;
showInstallationStatus?: boolean;
}

export const getLineClampStyles = (lineClamp?: number) =>
lineClamp
? `-webkit-line-clamp: ${lineClamp};display: -webkit-box;-webkit-box-orient: vertical;overflow: hidden;`
: '';

export const shouldShowInstallationStatus = ({
installStatus,
showInstallationStatus,
}: InstallationStatusProps) =>
showInstallationStatus &&
(installStatus === installationStatuses.Installed ||
installStatus === installationStatuses.InstallFailed);

export const InstallationStatus: React.FC<InstallationStatusProps> = React.memo(
({ installStatus, showInstallationStatus }) => {
const { euiTheme } = useEuiTheme();
return shouldShowInstallationStatus({ installStatus, showInstallationStatus }) ? (
<div
css={css`
position: absolute;
border-radius: 0 0 ${euiTheme.border.radius.medium} ${euiTheme.border.radius.medium};
bottom: 0;
left: 0;
width: 100%;
overflow: hidden;
`}
>
<EuiSpacer
data-test-subj="installation-status-spacer"
size="m"
css={css`
background: ${euiTheme.colors.emptyShade};
`}
/>
<EuiCallOut
data-test-subj="installation-status-callout"
css={css`
padding: ${euiTheme.size.s} ${euiTheme.size.m};
text-align: center;
`}
{...(installStatus ? installStatusMapToColor[installStatus] : {})}
/>
</div>
) : null;
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { useStartServices } from '../../../hooks';

import type { PackageCardProps } from './package_card';
import { PackageCard } from './package_card';
import { getLineClampStyles, shouldShowInstallationStatus } from './installation_status';

jest.mock('../../../hooks', () => {
return {
Expand All @@ -38,6 +39,16 @@ jest.mock('../../../components', () => {
};
});

jest.mock('./installation_status', () => {
return {
shouldShowInstallationStatus: jest.fn(),
getLineClampStyles: jest.fn(),
InstallationStatus: () => {
return <div data-test-subj="installation-status" />;
},
};
});

function cardProps(overrides: Partial<PackageCardProps> = {}): PackageCardProps {
return {
id: 'card-1',
Expand All @@ -60,8 +71,12 @@ function renderPackageCard(props: PackageCardProps) {
describe('package card', () => {
let mockNavigateToApp: jest.Mock;
let mockNavigateToUrl: jest.Mock;
const mockGetLineClamp = getLineClampStyles as jest.Mock;
const mockShouldShowInstallationStatus = shouldShowInstallationStatus as jest.Mock;

beforeEach(() => {
jest.clearAllMocks();

mockNavigateToApp = useStartServices().application.navigateToApp as jest.Mock;
mockNavigateToUrl = useStartServices().application.navigateToUrl as jest.Mock;
});
Expand Down Expand Up @@ -136,4 +151,83 @@ describe('package card', () => {
expect(!!collectionButton).toEqual(isCollectionCard);
}
);

describe('Installation status', () => {
it('should render installation status when showInstallationStatus is true', async () => {
const {
utils: { queryByTestId },
} = renderPackageCard(
cardProps({
showInstallationStatus: true,
})
);
const installationStatus = queryByTestId('installation-status');
expect(installationStatus).toBeInTheDocument();
});

it('should render max-height when maxCardHeight is provided', async () => {
const {
utils: { queryByTestId },
} = renderPackageCard(
cardProps({
maxCardHeight: 150,
})
);
const card = queryByTestId(`integration-card:card-1`);
expect(card).toHaveStyle('max-height: 150px');
});

it('should render 1 line of description when descriptionLineClamp is provided and shouldShowInstallationStatus returns true', async () => {
mockShouldShowInstallationStatus.mockReturnValue(true);
renderPackageCard(
cardProps({
showInstallationStatus: true,
installStatus: 'installed',
descriptionLineClamp: 3,
})
);
expect(mockShouldShowInstallationStatus).toHaveBeenCalledWith({
installStatus: 'installed',
showInstallationStatus: true,
});
expect(mockGetLineClamp).toHaveBeenCalledWith(1);
});

it('should render specific lines of description when descriptionLineClamp is provided and shouldShowInstallationStatus returns false', async () => {
mockShouldShowInstallationStatus.mockReturnValue(false);
renderPackageCard(
cardProps({
showInstallationStatus: false,
installStatus: 'installed',
descriptionLineClamp: 3,
})
);
expect(mockShouldShowInstallationStatus).toHaveBeenCalledWith({
installStatus: 'installed',
showInstallationStatus: false,
});
expect(mockGetLineClamp).toHaveBeenCalledWith(3);
});

it('should not render line clamp when descriptionLineClamp is not provided', async () => {
mockShouldShowInstallationStatus.mockReturnValue(false);
renderPackageCard(
cardProps({
showInstallationStatus: true,
installStatus: 'installed',
})
);
expect(mockShouldShowInstallationStatus).not.toHaveBeenCalled();
});

it('should render specific lines of title when titleLineClamp is provided and shouldShowInstallationStatus returns false', async () => {
mockShouldShowInstallationStatus.mockReturnValue(false);
renderPackageCard(
cardProps({
titleLineClamp: 1,
})
);
expect(mockGetLineClamp).toHaveBeenCalledWith(1);
});
});
});
Loading

0 comments on commit b16a1f7

Please sign in to comment.