mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Cloud Posture] Add blank page graphic (#126750)
This commit is contained in:
parent
a5f410ecf7
commit
79363812b7
11 changed files with 229 additions and 104 deletions
|
@ -4,10 +4,11 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { useQuery } from 'react-query';
|
||||
import type { CspClientPluginStartDeps } from '../../types';
|
||||
import { CSP_KUBEBEAT_INDEX_PATTERN } from '../../../common/constants';
|
||||
import { useKibana } from '../../../../../../src/plugins/kibana_react/public';
|
||||
import { CSP_KUBEBEAT_INDEX_PATTERN } from '../../../common/constants';
|
||||
import { CspClientPluginStartDeps } from '../../types';
|
||||
|
||||
/**
|
||||
* TODO: use perfected kibana data views
|
|
@ -4,15 +4,37 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import React, { ComponentProps } from 'react';
|
||||
import React, { type ComponentProps } from 'react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import Chance from 'chance';
|
||||
import { coreMock } from '../../../../../src/core/public/mocks';
|
||||
import { createStubDataView } from '../../../../../src/plugins/data_views/public/data_views/data_view.stub';
|
||||
import { CSP_KUBEBEAT_INDEX_PATTERN } from '../../common/constants';
|
||||
import { useKubebeatDataView } from '../common/api/use_kubebeat_data_view';
|
||||
import { createNavigationItemFixture } from '../test/fixtures/navigation_item';
|
||||
import { createReactQueryResponse } from '../test/fixtures/react_query';
|
||||
import { TestProvider } from '../test/test_provider';
|
||||
import { CspPageTemplate, getSideNavItems } from './page_template';
|
||||
import {
|
||||
LOADING,
|
||||
NO_DATA_CONFIG_BUTTON,
|
||||
NO_DATA_CONFIG_DESCRIPTION,
|
||||
NO_DATA_CONFIG_TITLE,
|
||||
} from './translations';
|
||||
|
||||
const chance = new Chance();
|
||||
|
||||
const BLANK_PAGE_GRAPHIC_TEXTS = [
|
||||
NO_DATA_CONFIG_TITLE,
|
||||
NO_DATA_CONFIG_DESCRIPTION,
|
||||
NO_DATA_CONFIG_BUTTON,
|
||||
];
|
||||
|
||||
// Synchronized to the error message in the formatted message in `page_template.tsx`
|
||||
const ERROR_LOADING_DATA_DEFAULT_MESSAGE = "We couldn't fetch your cloud security posture data";
|
||||
|
||||
jest.mock('../common/api/use_kubebeat_data_view');
|
||||
|
||||
describe('getSideNavItems', () => {
|
||||
it('maps navigation items to side navigation items', () => {
|
||||
const navigationItem = createNavigationItemFixture();
|
||||
|
@ -36,40 +58,101 @@ describe('getSideNavItems', () => {
|
|||
});
|
||||
|
||||
describe('<CspPageTemplate />', () => {
|
||||
const renderCspPageTemplate = (props: ComponentProps<typeof CspPageTemplate>) => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
const renderCspPageTemplate = (props: ComponentProps<typeof CspPageTemplate> = {}) => {
|
||||
const mockCore = coreMock.createStart();
|
||||
|
||||
render(
|
||||
<TestProvider>
|
||||
<TestProvider
|
||||
core={{
|
||||
...mockCore,
|
||||
application: {
|
||||
...mockCore.application,
|
||||
capabilities: {
|
||||
...mockCore.application.capabilities,
|
||||
// This is required so that the `noDataConfig` view will show the action button
|
||||
navLinks: { integrations: true },
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<CspPageTemplate {...props} />
|
||||
</TestProvider>
|
||||
);
|
||||
};
|
||||
|
||||
it('renders children when not loading', () => {
|
||||
it('renders children when data view is found', () => {
|
||||
(useKubebeatDataView as jest.Mock).mockImplementation(() =>
|
||||
createReactQueryResponse({
|
||||
status: 'success',
|
||||
data: createStubDataView({
|
||||
spec: {
|
||||
id: CSP_KUBEBEAT_INDEX_PATTERN,
|
||||
},
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
const children = chance.sentence();
|
||||
renderCspPageTemplate({ isLoading: false, children });
|
||||
renderCspPageTemplate({ children });
|
||||
|
||||
expect(screen.getByText(children)).toBeInTheDocument();
|
||||
expect(screen.queryByText(LOADING)).not.toBeInTheDocument();
|
||||
expect(screen.queryByText(ERROR_LOADING_DATA_DEFAULT_MESSAGE)).not.toBeInTheDocument();
|
||||
BLANK_PAGE_GRAPHIC_TEXTS.forEach((blankPageGraphicText) =>
|
||||
expect(screen.queryByText(blankPageGraphicText)).not.toBeInTheDocument()
|
||||
);
|
||||
});
|
||||
|
||||
it('does not render loading text when not loading', () => {
|
||||
it('renders loading text when data view is loading', () => {
|
||||
(useKubebeatDataView as jest.Mock).mockImplementation(() =>
|
||||
createReactQueryResponse({ status: 'loading' })
|
||||
);
|
||||
|
||||
const children = chance.sentence();
|
||||
const loadingText = chance.sentence();
|
||||
renderCspPageTemplate({ isLoading: false, loadingText, children });
|
||||
renderCspPageTemplate({ children });
|
||||
|
||||
expect(screen.queryByText(loadingText)).not.toBeInTheDocument();
|
||||
expect(screen.getByText(LOADING)).toBeInTheDocument();
|
||||
expect(screen.queryByText(children)).not.toBeInTheDocument();
|
||||
expect(screen.queryByText(ERROR_LOADING_DATA_DEFAULT_MESSAGE)).not.toBeInTheDocument();
|
||||
BLANK_PAGE_GRAPHIC_TEXTS.forEach((blankPageGraphicText) =>
|
||||
expect(screen.queryByText(blankPageGraphicText)).not.toBeInTheDocument()
|
||||
);
|
||||
});
|
||||
|
||||
it('renders loading text when loading is true', () => {
|
||||
const loadingText = chance.sentence();
|
||||
renderCspPageTemplate({ loadingText, isLoading: true });
|
||||
it('renders an error view when data view fetching has an error', () => {
|
||||
(useKubebeatDataView as jest.Mock).mockImplementation(() =>
|
||||
createReactQueryResponse({ status: 'error', error: new Error('') })
|
||||
);
|
||||
|
||||
expect(screen.getByText(loadingText)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('does not render children when loading', () => {
|
||||
const children = chance.sentence();
|
||||
renderCspPageTemplate({ isLoading: true, children });
|
||||
renderCspPageTemplate({ children });
|
||||
|
||||
expect(screen.getByText(ERROR_LOADING_DATA_DEFAULT_MESSAGE)).toBeInTheDocument();
|
||||
expect(screen.queryByText(LOADING)).not.toBeInTheDocument();
|
||||
expect(screen.queryByText(children)).not.toBeInTheDocument();
|
||||
BLANK_PAGE_GRAPHIC_TEXTS.forEach((blankPageGraphicText) =>
|
||||
expect(screen.queryByText(blankPageGraphicText)).not.toBeInTheDocument()
|
||||
);
|
||||
});
|
||||
|
||||
it('renders the blank page graphic when data view is missing', () => {
|
||||
(useKubebeatDataView as jest.Mock).mockImplementation(() =>
|
||||
createReactQueryResponse({
|
||||
status: 'success',
|
||||
data: undefined,
|
||||
})
|
||||
);
|
||||
|
||||
const children = chance.sentence();
|
||||
renderCspPageTemplate({ children });
|
||||
|
||||
BLANK_PAGE_GRAPHIC_TEXTS.forEach((text) => expect(screen.getByText(text)).toBeInTheDocument());
|
||||
expect(screen.queryByText(ERROR_LOADING_DATA_DEFAULT_MESSAGE)).not.toBeInTheDocument();
|
||||
expect(screen.queryByText(LOADING)).not.toBeInTheDocument();
|
||||
expect(screen.queryByText(children)).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,20 +4,26 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EuiSpacer } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import { EuiErrorBoundary } from '@elastic/eui';
|
||||
import { EuiEmptyPrompt, EuiErrorBoundary, EuiTitle } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import {
|
||||
KibanaPageTemplate,
|
||||
KibanaPageTemplateProps,
|
||||
type KibanaPageTemplateProps,
|
||||
} from '../../../../../src/plugins/kibana_react/public';
|
||||
import { useKubebeatDataView } from '../common/api/use_kubebeat_data_view';
|
||||
import { allNavigationItems } from '../common/navigation/constants';
|
||||
import type { CspNavigationItem } from '../common/navigation/types';
|
||||
import { CLOUD_SECURITY_POSTURE } from '../common/translations';
|
||||
import { CspLoadingState } from './csp_loading_state';
|
||||
import { LOADING } from './translations';
|
||||
import {
|
||||
LOADING,
|
||||
NO_DATA_CONFIG_BUTTON,
|
||||
NO_DATA_CONFIG_DESCRIPTION,
|
||||
NO_DATA_CONFIG_SOLUTION_NAME,
|
||||
NO_DATA_CONFIG_TITLE,
|
||||
} from './translations';
|
||||
|
||||
const activeItemStyle = { fontWeight: 700 };
|
||||
|
||||
|
@ -36,37 +42,69 @@ export const getSideNavItems = (
|
|||
),
|
||||
}));
|
||||
|
||||
const defaultProps: KibanaPageTemplateProps = {
|
||||
const DEFAULT_PROPS: KibanaPageTemplateProps = {
|
||||
solutionNav: {
|
||||
name: CLOUD_SECURITY_POSTURE,
|
||||
items: getSideNavItems(allNavigationItems),
|
||||
},
|
||||
restrictWidth: false,
|
||||
template: 'default',
|
||||
};
|
||||
|
||||
interface CspPageTemplateProps extends KibanaPageTemplateProps {
|
||||
isLoading?: boolean;
|
||||
loadingText?: string;
|
||||
}
|
||||
const NO_DATA_CONFIG: KibanaPageTemplateProps['noDataConfig'] = {
|
||||
pageTitle: NO_DATA_CONFIG_TITLE,
|
||||
solution: NO_DATA_CONFIG_SOLUTION_NAME,
|
||||
// TODO: Add real docs link once we have it
|
||||
docsLink: 'https://www.elastic.co/guide/index.html',
|
||||
logo: 'logoSecurity',
|
||||
actions: {
|
||||
elasticAgent: {
|
||||
// TODO: Use `href` prop to link to our own integration once we have it
|
||||
title: NO_DATA_CONFIG_BUTTON,
|
||||
description: NO_DATA_CONFIG_DESCRIPTION,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const CspPageTemplate: React.FC<KibanaPageTemplateProps> = ({ children, ...props }) => {
|
||||
// TODO: Consider using more sophisticated logic to find out if our integration is installed
|
||||
const kubeBeatQuery = useKubebeatDataView();
|
||||
|
||||
let noDataConfig: KibanaPageTemplateProps['noDataConfig'];
|
||||
if (kubeBeatQuery.status === 'success' && !kubeBeatQuery.data) {
|
||||
noDataConfig = NO_DATA_CONFIG;
|
||||
}
|
||||
|
||||
let template: KibanaPageTemplateProps['template'] = 'default';
|
||||
if (kubeBeatQuery.status === 'error' || kubeBeatQuery.status === 'loading') {
|
||||
template = 'centeredContent';
|
||||
}
|
||||
|
||||
export const CspPageTemplate: React.FC<CspPageTemplateProps> = ({
|
||||
children,
|
||||
isLoading,
|
||||
loadingText = LOADING,
|
||||
...props
|
||||
}) => {
|
||||
return (
|
||||
<KibanaPageTemplate {...defaultProps} {...props}>
|
||||
<KibanaPageTemplate
|
||||
{...DEFAULT_PROPS}
|
||||
{...props}
|
||||
template={template}
|
||||
noDataConfig={noDataConfig}
|
||||
>
|
||||
<EuiErrorBoundary>
|
||||
{isLoading ? (
|
||||
<>
|
||||
<EuiSpacer size="xxl" />
|
||||
<CspLoadingState>{loadingText}</CspLoadingState>
|
||||
</>
|
||||
) : (
|
||||
children
|
||||
{kubeBeatQuery.status === 'loading' && <CspLoadingState>{LOADING}</CspLoadingState>}
|
||||
{kubeBeatQuery.status === 'error' && (
|
||||
<EuiEmptyPrompt
|
||||
color="danger"
|
||||
iconType="alert"
|
||||
title={
|
||||
<EuiTitle>
|
||||
<h2>
|
||||
<FormattedMessage
|
||||
id="xpack.csp.pageTemplate.loadErrorMessage"
|
||||
defaultMessage="We couldn't fetch your cloud security posture data"
|
||||
/>
|
||||
</h2>
|
||||
</EuiTitle>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{kubeBeatQuery.status === 'success' && children}
|
||||
</EuiErrorBoundary>
|
||||
</KibanaPageTemplate>
|
||||
);
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
export const CRITICAL = i18n.translate('xpack.csp.critical', {
|
||||
|
@ -40,3 +39,29 @@ export const CSP_EVALUATION_BADGE_PASSED = i18n.translate(
|
|||
defaultMessage: 'PASSED',
|
||||
}
|
||||
);
|
||||
|
||||
export const NO_DATA_CONFIG_TITLE = i18n.translate('xpack.csp.pageTemplate.noDataConfigTitle', {
|
||||
defaultMessage: 'Understand your cloud security posture',
|
||||
});
|
||||
|
||||
export const NO_DATA_CONFIG_SOLUTION_NAME = i18n.translate(
|
||||
'xpack.csp.pageTemplate.noDataConfig.solutionNameLabel',
|
||||
{
|
||||
defaultMessage: 'Cloud Security Posture',
|
||||
}
|
||||
);
|
||||
|
||||
export const NO_DATA_CONFIG_DESCRIPTION = i18n.translate(
|
||||
'xpack.csp.pageTemplate.noDataConfigDescription',
|
||||
{
|
||||
defaultMessage:
|
||||
'Use our CIS Kubernetes Benchmark integration to measure your Kubernetes cluster setup against the CIS recommendations.',
|
||||
}
|
||||
);
|
||||
|
||||
export const NO_DATA_CONFIG_BUTTON = i18n.translate(
|
||||
'xpack.csp.pageTemplate.noDataConfigButtonLabel',
|
||||
{
|
||||
defaultMessage: 'Add a CIS integration',
|
||||
}
|
||||
);
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
import React from 'react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import type { UseQueryResult } from 'react-query/types/react/types';
|
||||
import { createStubDataView } from '../../../../../../src/plugins/data_views/public/data_views/data_view.stub';
|
||||
import { CSP_KUBEBEAT_INDEX_PATTERN } from '../../../common/constants';
|
||||
import { useKubebeatDataView } from '../../common/api/use_kubebeat_data_view';
|
||||
import { createCspBenchmarkIntegrationFixture } from '../../test/fixtures/csp_benchmark_integration';
|
||||
import { createReactQueryResponse } from '../../test/fixtures/react_query';
|
||||
import { TestProvider } from '../../test/test_provider';
|
||||
|
@ -15,10 +18,22 @@ import { ADD_A_CIS_INTEGRATION, BENCHMARK_INTEGRATIONS, LOADING_BENCHMARKS } fro
|
|||
import { useCspBenchmarkIntegrations } from './use_csp_benchmark_integrations';
|
||||
|
||||
jest.mock('./use_csp_benchmark_integrations');
|
||||
jest.mock('../../common/api/use_kubebeat_data_view');
|
||||
|
||||
describe('<Benchmarks />', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
// Required for the page template to render the benchmarks page
|
||||
(useKubebeatDataView as jest.Mock).mockImplementation(() =>
|
||||
createReactQueryResponse({
|
||||
status: 'success',
|
||||
data: createStubDataView({
|
||||
spec: {
|
||||
id: CSP_KUBEBEAT_INDEX_PATTERN,
|
||||
},
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
const renderBenchmarks = (
|
||||
|
|
|
@ -4,10 +4,11 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import { EuiPageHeaderProps, EuiButton } from '@elastic/eui';
|
||||
import { EuiPageHeaderProps, EuiButton, EuiSpacer } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import { allNavigationItems } from '../../common/navigation/constants';
|
||||
import { useCspBreadcrumbs } from '../../common/navigation/use_csp_breadcrumbs';
|
||||
import { CspLoadingState } from '../../components/csp_loading_state';
|
||||
import { CspPageTemplate } from '../../components/page_template';
|
||||
import { BenchmarksTable } from './benchmarks_table';
|
||||
import { ADD_A_CIS_INTEGRATION, BENCHMARK_INTEGRATIONS, LOADING_BENCHMARKS } from './translations';
|
||||
|
@ -35,11 +36,13 @@ export const Benchmarks = () => {
|
|||
const query = useCspBenchmarkIntegrations();
|
||||
|
||||
return (
|
||||
<CspPageTemplate
|
||||
pageHeader={PAGE_HEADER}
|
||||
loadingText={LOADING_BENCHMARKS}
|
||||
isLoading={query.status === 'loading'}
|
||||
>
|
||||
<CspPageTemplate pageHeader={PAGE_HEADER}>
|
||||
{query.status === 'loading' && (
|
||||
<>
|
||||
<EuiSpacer size="xxl" />
|
||||
<CspLoadingState>{LOADING_BENCHMARKS}</CspLoadingState>
|
||||
</>
|
||||
)}
|
||||
{query.status === 'error' && <BenchmarksErrorState />}
|
||||
{query.status === 'success' && (
|
||||
<BenchmarksTable benchmarks={query.data} data-test-subj={BENCHMARKS_TABLE_DATA_TEST_SUBJ} />
|
||||
|
|
|
@ -7,49 +7,31 @@
|
|||
import React from 'react';
|
||||
import type { UseQueryResult } from 'react-query';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { useKubebeatDataView } from '../../common/api/use_kubebeat_data_view';
|
||||
import { Findings } from './findings';
|
||||
import { MISSING_KUBEBEAT } from './translations';
|
||||
import { TestProvider } from '../../test/test_provider';
|
||||
import { dataPluginMock } from '../../../../../../src/plugins/data/public/mocks';
|
||||
import {
|
||||
dataPluginMock,
|
||||
type Start as DataPluginStart,
|
||||
} from '../../../../../../src/plugins/data/public/mocks';
|
||||
import { createStubDataView } from '../../../../../../src/plugins/data_views/public/data_views/data_view.stub';
|
||||
import { useKubebeatDataView } from './utils';
|
||||
import { CSP_KUBEBEAT_INDEX_PATTERN } from '../../../common/constants';
|
||||
import * as TEST_SUBJECTS from './test_subjects';
|
||||
import type { DataView } from '../../../../../../src/plugins/data/common';
|
||||
|
||||
jest.mock('./utils');
|
||||
jest.mock('../../common/api/use_kubebeat_data_view');
|
||||
|
||||
beforeEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
const Wrapper = ({ data = dataPluginMock.createStartContract() }) => (
|
||||
const Wrapper = ({ data = dataPluginMock.createStartContract() }: { data: DataPluginStart }) => (
|
||||
<TestProvider deps={{ data }}>
|
||||
<Findings />
|
||||
</TestProvider>
|
||||
);
|
||||
|
||||
describe('<Findings />', () => {
|
||||
it("renders the error state component when 'kubebeat' DataView doesn't exists", async () => {
|
||||
(useKubebeatDataView as jest.Mock).mockReturnValue({
|
||||
status: 'success',
|
||||
} as UseQueryResult<DataView>);
|
||||
|
||||
render(<Wrapper />);
|
||||
|
||||
expect(await screen.findByText(MISSING_KUBEBEAT)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders the error state component when 'kubebeat' request status is 'error'", async () => {
|
||||
(useKubebeatDataView as jest.Mock).mockReturnValue({
|
||||
status: 'error',
|
||||
} as UseQueryResult<DataView>);
|
||||
|
||||
render(<Wrapper />);
|
||||
|
||||
expect(await screen.findByText(MISSING_KUBEBEAT)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders the success state component when 'kubebeat' DataView exists and request status is 'success'", async () => {
|
||||
const data = dataPluginMock.createStartContract();
|
||||
const source = await data.search.searchSource.create();
|
||||
|
|
|
@ -5,15 +5,13 @@
|
|||
* 2.0.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { EuiEmptyPrompt, EuiLoadingSpinner } from '@elastic/eui';
|
||||
import type { EuiPageHeaderProps } from '@elastic/eui';
|
||||
import { useKubebeatDataView } from '../../common/api/use_kubebeat_data_view';
|
||||
import { allNavigationItems } from '../../common/navigation/constants';
|
||||
import { useCspBreadcrumbs } from '../../common/navigation/use_csp_breadcrumbs';
|
||||
import { FindingsContainer } from './findings_container';
|
||||
import { CspPageTemplate } from '../../components/page_template';
|
||||
import { useKubebeatDataView } from './utils';
|
||||
import * as TEST_SUBJECTS from './test_subjects';
|
||||
import { FINDINGS, MISSING_KUBEBEAT } from './translations';
|
||||
import { FINDINGS } from './translations';
|
||||
|
||||
const pageHeader: EuiPageHeaderProps = {
|
||||
pageTitle: FINDINGS,
|
||||
|
@ -24,27 +22,11 @@ export const Findings = () => {
|
|||
useCspBreadcrumbs([allNavigationItems.findings]);
|
||||
|
||||
return (
|
||||
// `CspPageTemplate` takes care of loading and error states for the kubebeat data view, no need to handle them here
|
||||
<CspPageTemplate pageHeader={pageHeader}>
|
||||
{dataView.status === 'loading' && <LoadingPrompt />}
|
||||
{(dataView.status === 'error' || (dataView.status !== 'loading' && !dataView.data)) && (
|
||||
<ErrorPrompt />
|
||||
)}
|
||||
{dataView.status === 'success' && dataView.data && (
|
||||
<FindingsContainer dataView={dataView.data} />
|
||||
)}
|
||||
</CspPageTemplate>
|
||||
);
|
||||
};
|
||||
|
||||
const LoadingPrompt = () => <EuiEmptyPrompt icon={<EuiLoadingSpinner size="xl" />} />;
|
||||
|
||||
// TODO: follow https://elastic.github.io/eui/#/display/empty-prompt/guidelines
|
||||
const ErrorPrompt = () => (
|
||||
<EuiEmptyPrompt
|
||||
data-test-subj={TEST_SUBJECTS.FINDINGS_MISSING_INDEX}
|
||||
color="danger"
|
||||
iconType="alert"
|
||||
// TODO: account for when we have a dataview without an index
|
||||
title={<h2>{MISSING_KUBEBEAT}</h2>}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -8,5 +8,4 @@
|
|||
export const FINDINGS_SEARCH_BAR = 'findings_search_bar';
|
||||
export const FINDINGS_TABLE = 'findings_table';
|
||||
export const FINDINGS_CONTAINER = 'findings_container';
|
||||
export const FINDINGS_MISSING_INDEX = 'findings_page_missing_dataview';
|
||||
export const FINDINGS_TABLE_ZERO_STATE = 'findings_table_zero_state';
|
||||
|
|
|
@ -30,10 +30,6 @@ export const FINDINGS = i18n.translate('xpack.csp.findings', {
|
|||
defaultMessage: 'Findings',
|
||||
});
|
||||
|
||||
export const MISSING_KUBEBEAT = i18n.translate('xpack.csp.kubebeatDataViewIsMissing', {
|
||||
defaultMessage: 'Kubebeat DataView is missing',
|
||||
});
|
||||
|
||||
export const RESOURCE = i18n.translate('xpack.csp.resource', {
|
||||
defaultMessage: 'Resource',
|
||||
});
|
||||
|
|
|
@ -10,18 +10,19 @@ import { I18nProvider } from '@kbn/i18n-react';
|
|||
import { Router, Switch, Route } from 'react-router-dom';
|
||||
import { QueryClient, QueryClientProvider } from 'react-query';
|
||||
import { coreMock } from '../../../../../src/core/public/mocks';
|
||||
import { dataPluginMock } from '../../../../../src/plugins/data/public/mocks';
|
||||
import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public';
|
||||
import type { CspAppDeps } from '../application/app';
|
||||
|
||||
export const TestProvider: React.FC<Partial<CspAppDeps>> = ({
|
||||
core = coreMock.createStart(),
|
||||
deps = {},
|
||||
deps = { data: dataPluginMock.createStartContract() },
|
||||
params = coreMock.createAppMountParameters(),
|
||||
children,
|
||||
} = {}) => {
|
||||
const queryClient = useMemo(() => new QueryClient(), []);
|
||||
return (
|
||||
<KibanaContextProvider services={{ ...deps, ...core }}>
|
||||
<KibanaContextProvider services={{ ...core, ...deps }}>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<Router history={params.history}>
|
||||
<I18nProvider>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue