Jest and Storybook fixes (#116132)
* Fix all broken stories * In stories that were broken, add an associated Jest test so they if they break in the future we'll know * Fix all console.error messages that were being printed during Jest test runs * Add test setup which makes it so `console.error` throws an error so tests will fail if error console messages are printed
This commit is contained in:
parent
3c8fa527a7
commit
57c2555f27
23 changed files with 496 additions and 1600 deletions
|
@ -11,7 +11,10 @@ module.exports = {
|
|||
preset: '@kbn/test',
|
||||
rootDir: path.resolve(__dirname, '../../..'),
|
||||
roots: ['<rootDir>/x-pack/plugins/apm'],
|
||||
setupFiles: ['<rootDir>/x-pack/plugins/apm/.storybook/jest_setup.js'],
|
||||
setupFiles: [
|
||||
'<rootDir>/x-pack/plugins/apm/jest_setup.js',
|
||||
'<rootDir>/x-pack/plugins/apm/.storybook/jest_setup.js',
|
||||
],
|
||||
coverageDirectory: '<rootDir>/target/kibana-coverage/jest/x-pack/plugins/apm',
|
||||
coverageReporters: ['text', 'html'],
|
||||
collectCoverageFrom: [
|
||||
|
|
14
x-pack/plugins/apm/jest_setup.js
Normal file
14
x-pack/plugins/apm/jest_setup.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* global jest */
|
||||
|
||||
// When a `console.error` is encountered, throw the error to make the test fail.
|
||||
// This effectively treats logged errors during the test run as failures.
|
||||
jest.spyOn(console, 'error').mockImplementation((message) => {
|
||||
throw new Error(message);
|
||||
});
|
|
@ -11,11 +11,17 @@ import { AlertParams, ErrorCountAlertTrigger } from '.';
|
|||
import { CoreStart } from '../../../../../../../src/core/public';
|
||||
import { createKibanaReactContext } from '../../../../../../../src/plugins/kibana_react/public';
|
||||
import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values';
|
||||
import { createCallApmApi } from '../../../services/rest/createCallApmApi';
|
||||
|
||||
import { AlertMetadata } from '../helper';
|
||||
|
||||
const KibanaReactContext = createKibanaReactContext({
|
||||
const coreMock = {
|
||||
http: { get: async () => ({}) },
|
||||
notifications: { toasts: { add: () => {} } },
|
||||
} as unknown as Partial<CoreStart>);
|
||||
uiSettings: { get: () => {} },
|
||||
} as unknown as CoreStart;
|
||||
|
||||
const KibanaReactContext = createKibanaReactContext(coreMock);
|
||||
|
||||
interface Args {
|
||||
alertParams: AlertParams;
|
||||
|
@ -27,6 +33,8 @@ const stories: Meta<{}> = {
|
|||
component: ErrorCountAlertTrigger,
|
||||
decorators: [
|
||||
(StoryComponent) => {
|
||||
createCallApmApi(coreMock);
|
||||
|
||||
return (
|
||||
<KibanaReactContext.Provider>
|
||||
<div style={{ width: 400 }}>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { render } from '@testing-library/react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import * as stories from './error_count_alert_trigger.stories';
|
||||
import { composeStories } from '@storybook/testing-react';
|
||||
|
@ -13,7 +13,9 @@ import { composeStories } from '@storybook/testing-react';
|
|||
const { CreatingInApmFromService } = composeStories(stories);
|
||||
|
||||
describe('ErrorCountAlertTrigger', () => {
|
||||
it('renders', () => {
|
||||
expect(() => render(<CreatingInApmFromService />)).not.toThrowError();
|
||||
it('renders', async () => {
|
||||
render(<CreatingInApmFromService />);
|
||||
|
||||
expect(await screen.findByText('Service')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* 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 { mount } from 'enzyme';
|
||||
import React from 'react';
|
||||
import { MockApmPluginContextWrapper } from '../../../../context/apm_plugin/mock_apm_plugin_context';
|
||||
import { MockUrlParamsContextProvider } from '../../../../context/url_params_context/mock_url_params_context_provider';
|
||||
import { mockMoment, toJson } from '../../../../utils/testHelpers';
|
||||
import { ErrorGroupList } from './index';
|
||||
import props from './__fixtures__/props.json';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { EuiThemeProvider } from '../../../../../../../../src/plugins/kibana_react/common';
|
||||
|
||||
describe('ErrorGroupOverview -> List', () => {
|
||||
beforeAll(() => {
|
||||
mockMoment();
|
||||
});
|
||||
|
||||
it('should render empty state', () => {
|
||||
const storeState = {};
|
||||
const wrapper = mount(
|
||||
<MemoryRouter>
|
||||
<MockUrlParamsContextProvider>
|
||||
<ErrorGroupList items={[]} serviceName="opbeans-python" />
|
||||
</MockUrlParamsContextProvider>
|
||||
</MemoryRouter>,
|
||||
storeState
|
||||
);
|
||||
|
||||
expect(toJson(wrapper)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render with data', () => {
|
||||
const wrapper = mount(
|
||||
<EuiThemeProvider>
|
||||
<MemoryRouter>
|
||||
<MockApmPluginContextWrapper>
|
||||
<MockUrlParamsContextProvider>
|
||||
<ErrorGroupList
|
||||
items={props.items}
|
||||
serviceName="opbeans-python"
|
||||
/>
|
||||
</MockUrlParamsContextProvider>
|
||||
</MockApmPluginContextWrapper>
|
||||
</MemoryRouter>
|
||||
</EuiThemeProvider>
|
||||
);
|
||||
|
||||
expect(toJson(wrapper)).toMatchSnapshot();
|
||||
});
|
||||
});
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* 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 { Meta, Story } from '@storybook/react';
|
||||
import React, { ComponentProps } from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { MockApmPluginContextWrapper } from '../../../../context/apm_plugin/mock_apm_plugin_context';
|
||||
import { MockUrlParamsContextProvider } from '../../../../context/url_params_context/mock_url_params_context_provider';
|
||||
|
||||
import { ErrorGroupList } from '.';
|
||||
|
||||
type Args = ComponentProps<typeof ErrorGroupList>;
|
||||
|
||||
const stories: Meta<Args> = {
|
||||
title: 'app/ErrorGroupOverview/ErrorGroupList',
|
||||
component: ErrorGroupList,
|
||||
decorators: [
|
||||
(StoryComponent) => {
|
||||
return (
|
||||
<MemoryRouter>
|
||||
<MockApmPluginContextWrapper>
|
||||
<MockUrlParamsContextProvider>
|
||||
<StoryComponent />
|
||||
</MockUrlParamsContextProvider>
|
||||
</MockApmPluginContextWrapper>
|
||||
</MemoryRouter>
|
||||
);
|
||||
},
|
||||
],
|
||||
};
|
||||
export default stories;
|
||||
|
||||
export const Example: Story<Args> = (args) => {
|
||||
return <ErrorGroupList {...args} />;
|
||||
};
|
||||
Example.args = {
|
||||
items: [
|
||||
{
|
||||
message: 'net/http: abort Handler',
|
||||
occurrenceCount: 14,
|
||||
culprit: 'Main.func2',
|
||||
groupId: '83a653297ec29afed264d7b60d5cda7b',
|
||||
latestOccurrenceAt: '2021-10-21T16:18:41.434Z',
|
||||
handled: false,
|
||||
type: 'errorString',
|
||||
},
|
||||
{
|
||||
message: 'POST /api/orders (500)',
|
||||
occurrenceCount: 5,
|
||||
culprit: 'logrusMiddleware',
|
||||
groupId: '7a640436a9be648fd708703d1ac84650',
|
||||
latestOccurrenceAt: '2021-10-21T16:18:40.162Z',
|
||||
handled: false,
|
||||
type: 'OpError',
|
||||
},
|
||||
{
|
||||
message:
|
||||
'write tcp 10.36.2.24:3000->10.36.1.14:34232: write: connection reset by peer',
|
||||
occurrenceCount: 4,
|
||||
culprit: 'apiHandlers.getProductCustomers',
|
||||
groupId: '95ca0e312c109aa11e298bcf07f1445b',
|
||||
latestOccurrenceAt: '2021-10-21T16:18:42.650Z',
|
||||
handled: false,
|
||||
type: 'OpError',
|
||||
},
|
||||
{
|
||||
message:
|
||||
'write tcp 10.36.0.21:3000->10.36.1.252:57070: write: connection reset by peer',
|
||||
occurrenceCount: 3,
|
||||
culprit: 'apiHandlers.getCustomers',
|
||||
groupId: '4053d7e33d2b716c819bd96d9d6121a2',
|
||||
latestOccurrenceAt: '2021-10-21T16:07:44.078Z',
|
||||
handled: false,
|
||||
type: 'OpError',
|
||||
},
|
||||
{
|
||||
message:
|
||||
'write tcp 10.36.0.21:3000->10.36.0.88:33926: write: broken pipe',
|
||||
occurrenceCount: 2,
|
||||
culprit: 'apiHandlers.getOrders',
|
||||
groupId: '94f4ca8ec8c02e5318cf03f46ae4c1f3',
|
||||
latestOccurrenceAt: '2021-10-21T16:13:45.742Z',
|
||||
handled: false,
|
||||
type: 'OpError',
|
||||
},
|
||||
],
|
||||
serviceName: 'test service',
|
||||
};
|
||||
|
||||
export const EmptyState: Story<Args> = (args) => {
|
||||
return <ErrorGroupList {...args} />;
|
||||
};
|
||||
EmptyState.args = {
|
||||
items: [],
|
||||
serviceName: 'test service',
|
||||
};
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* 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 { composeStories } from '@storybook/testing-react';
|
||||
import { render } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import * as stories from './error_group_list.stories';
|
||||
|
||||
const { Example } = composeStories(stories);
|
||||
|
||||
describe('ErrorGroupList', () => {
|
||||
it('renders', () => {
|
||||
expect(() => render(<Example />)).not.toThrowError();
|
||||
});
|
||||
});
|
|
@ -23,7 +23,7 @@ import { useFetcher } from '../../../hooks/use_fetcher';
|
|||
import { useTimeRange } from '../../../hooks/use_time_range';
|
||||
import { FailedTransactionRateChart } from '../../shared/charts/failed_transaction_rate_chart';
|
||||
import { ErrorDistribution } from '../error_group_details/Distribution';
|
||||
import { ErrorGroupList } from './List';
|
||||
import { ErrorGroupList } from './error_group_list';
|
||||
|
||||
export function ErrorGroupOverview() {
|
||||
const { serviceName } = useApmServiceContext();
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* 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 { Meta, Story } from '@storybook/react';
|
||||
import React, { ComponentProps } from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { CoreStart } from '../../../../../../../../src/core/public';
|
||||
import { createKibanaReactContext } from '../../../../../../../../src/plugins/kibana_react/public';
|
||||
import { ServiceHealthStatus } from '../../../../../common/service_health_status';
|
||||
import type { ApmPluginContextValue } from '../../../../context/apm_plugin/apm_plugin_context';
|
||||
import { MockApmPluginContextWrapper } from '../../../../context/apm_plugin/mock_apm_plugin_context';
|
||||
import { ServiceList } from './';
|
||||
import { items } from './__fixtures__/service_api_mock_data';
|
||||
|
||||
type Args = ComponentProps<typeof ServiceList>;
|
||||
|
||||
const coreMock = {
|
||||
http: {
|
||||
get: async () => {
|
||||
return { fallBackToTransactions: false };
|
||||
},
|
||||
},
|
||||
notifications: { toasts: { add: () => {} } },
|
||||
uiSettings: { get: () => ({}) },
|
||||
} as unknown as CoreStart;
|
||||
|
||||
const KibanaReactContext = createKibanaReactContext(coreMock);
|
||||
|
||||
const stories: Meta<Args> = {
|
||||
title: 'app/ServiceInventory/ServiceList',
|
||||
component: ServiceList,
|
||||
decorators: [
|
||||
(StoryComponent) => {
|
||||
return (
|
||||
<KibanaReactContext.Provider>
|
||||
<MemoryRouter
|
||||
initialEntries={['/services?rangeFrom=now-15m&rangeTo=now']}
|
||||
>
|
||||
<MockApmPluginContextWrapper
|
||||
value={{ core: coreMock } as unknown as ApmPluginContextValue}
|
||||
>
|
||||
<StoryComponent />
|
||||
</MockApmPluginContextWrapper>
|
||||
</MemoryRouter>
|
||||
</KibanaReactContext.Provider>
|
||||
);
|
||||
},
|
||||
],
|
||||
};
|
||||
export default stories;
|
||||
|
||||
export const Example: Story<Args> = (args) => {
|
||||
return <ServiceList {...args} />;
|
||||
};
|
||||
Example.args = {
|
||||
isLoading: false,
|
||||
items,
|
||||
};
|
||||
|
||||
export const EmptyState: Story<Args> = (args) => {
|
||||
return <ServiceList {...args} />;
|
||||
};
|
||||
EmptyState.args = {
|
||||
isLoading: false,
|
||||
items: [],
|
||||
};
|
||||
|
||||
export const WithHealthWarnings: Story<Args> = (args) => {
|
||||
return <ServiceList {...args} />;
|
||||
};
|
||||
WithHealthWarnings.args = {
|
||||
isLoading: false,
|
||||
items: items.map((item) => ({
|
||||
...item,
|
||||
healthStatus: ServiceHealthStatus.warning,
|
||||
})),
|
||||
};
|
|
@ -5,58 +5,27 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { ReactNode } from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { Breakpoints } from '../../../../hooks/use_breakpoints';
|
||||
import { ServiceHealthStatus } from '../../../../../common/service_health_status';
|
||||
import { MockApmPluginContextWrapper } from '../../../../context/apm_plugin/mock_apm_plugin_context';
|
||||
import { mockMoment, renderWithTheme } from '../../../../utils/testHelpers';
|
||||
import { getServiceColumns, ServiceList } from './';
|
||||
import { items } from './__fixtures__/service_api_mock_data';
|
||||
import { composeStories } from '@storybook/testing-react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { ENVIRONMENT_ALL } from '../../../../../common/environment_filter_values';
|
||||
import {
|
||||
getCallApmApiSpy,
|
||||
getCreateCallApmApiSpy,
|
||||
} from '../../../../services/rest/callApmApiSpy';
|
||||
import { Breakpoints } from '../../../../hooks/use_breakpoints';
|
||||
import { getServiceColumns } from './';
|
||||
import * as stories from './service_list.stories';
|
||||
|
||||
function Wrapper({ children }: { children?: ReactNode }) {
|
||||
return (
|
||||
<MemoryRouter initialEntries={['/services?rangeFrom=now-15m&rangeTo=now']}>
|
||||
<MockApmPluginContextWrapper>{children}</MockApmPluginContextWrapper>
|
||||
</MemoryRouter>
|
||||
);
|
||||
}
|
||||
const { Example, EmptyState, WithHealthWarnings } = composeStories(stories);
|
||||
|
||||
describe('ServiceList', () => {
|
||||
beforeAll(() => {
|
||||
mockMoment();
|
||||
it('renders empty state', async () => {
|
||||
render(<EmptyState />);
|
||||
|
||||
const callApmApiSpy = getCallApmApiSpy().mockImplementation(
|
||||
({ endpoint }) => {
|
||||
if (endpoint === 'GET /internal/apm/fallback_to_transactions') {
|
||||
return Promise.resolve({ fallbackToTransactions: false });
|
||||
}
|
||||
return Promise.reject(`Response for ${endpoint} is not defined`);
|
||||
}
|
||||
);
|
||||
|
||||
getCreateCallApmApiSpy().mockImplementation(() => callApmApiSpy as any);
|
||||
expect(await screen.findByRole('table')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders empty state', () => {
|
||||
expect(() =>
|
||||
renderWithTheme(<ServiceList isLoading={false} items={[]} />, {
|
||||
wrapper: Wrapper,
|
||||
})
|
||||
).not.toThrowError();
|
||||
});
|
||||
it('renders with data', async () => {
|
||||
render(<Example />);
|
||||
|
||||
it('renders with data', () => {
|
||||
expect(() =>
|
||||
renderWithTheme(<ServiceList isLoading={false} items={items} />, {
|
||||
wrapper: Wrapper,
|
||||
})
|
||||
).not.toThrowError();
|
||||
expect(await screen.findByRole('table')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe('responsive columns', () => {
|
||||
|
@ -212,44 +181,20 @@ describe('ServiceList', () => {
|
|||
});
|
||||
|
||||
describe('without ML data', () => {
|
||||
it('does not render the health column', () => {
|
||||
const { queryByText } = renderWithTheme(
|
||||
<ServiceList isLoading={false} items={items} />,
|
||||
{
|
||||
wrapper: Wrapper,
|
||||
}
|
||||
);
|
||||
const healthHeading = queryByText('Health');
|
||||
|
||||
expect(healthHeading).toBeNull();
|
||||
});
|
||||
|
||||
it('sorts by throughput', async () => {
|
||||
const { findByTitle } = renderWithTheme(
|
||||
<ServiceList isLoading={false} items={items} />,
|
||||
{
|
||||
wrapper: Wrapper,
|
||||
}
|
||||
);
|
||||
render(<Example />);
|
||||
|
||||
expect(await findByTitle('Throughput')).toBeInTheDocument();
|
||||
expect(await screen.findByTitle('Throughput')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('with ML data', () => {
|
||||
it('renders the health column', async () => {
|
||||
const { findByTitle } = renderWithTheme(
|
||||
<ServiceList
|
||||
isLoading={false}
|
||||
items={items.map((item) => ({
|
||||
...item,
|
||||
healthStatus: ServiceHealthStatus.warning,
|
||||
}))}
|
||||
/>,
|
||||
{ wrapper: Wrapper }
|
||||
);
|
||||
render(<WithHealthWarnings />);
|
||||
|
||||
expect(await findByTitle('Health')).toBeInTheDocument();
|
||||
expect(
|
||||
await screen.findByRole('button', { name: /Health/ })
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { __IntlProvider as IntlProvider } from '@kbn/i18n/react';
|
||||
import { render, screen, waitFor } from '@testing-library/react';
|
||||
import { createMemoryHistory } from 'history';
|
||||
import React, { ReactNode } from 'react';
|
||||
|
@ -49,25 +50,27 @@ function Wrapper({ children }: { children?: ReactNode }) {
|
|||
}) as unknown as ApmPluginContextValue;
|
||||
|
||||
return (
|
||||
<EuiThemeProvider darkMode={false}>
|
||||
<KibanaReactContext.Provider>
|
||||
<MockApmPluginContextWrapper
|
||||
history={history}
|
||||
value={mockPluginContext}
|
||||
>
|
||||
<MockUrlParamsContextProvider
|
||||
params={{
|
||||
rangeFrom: 'now-15m',
|
||||
rangeTo: 'now',
|
||||
start: 'mystart',
|
||||
end: 'myend',
|
||||
}}
|
||||
<IntlProvider locale="en">
|
||||
<EuiThemeProvider darkMode={false}>
|
||||
<KibanaReactContext.Provider>
|
||||
<MockApmPluginContextWrapper
|
||||
history={history}
|
||||
value={mockPluginContext}
|
||||
>
|
||||
{children}
|
||||
</MockUrlParamsContextProvider>
|
||||
</MockApmPluginContextWrapper>
|
||||
</KibanaReactContext.Provider>
|
||||
</EuiThemeProvider>
|
||||
<MockUrlParamsContextProvider
|
||||
params={{
|
||||
rangeFrom: 'now-15m',
|
||||
rangeTo: 'now',
|
||||
start: 'mystart',
|
||||
end: 'myend',
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</MockUrlParamsContextProvider>
|
||||
</MockApmPluginContextWrapper>
|
||||
</KibanaReactContext.Provider>
|
||||
</EuiThemeProvider>
|
||||
</IntlProvider>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -93,13 +96,13 @@ describe('transaction_details/distribution', () => {
|
|||
}));
|
||||
|
||||
render(
|
||||
<Wrapper>
|
||||
<TransactionDistribution
|
||||
onChartSelection={jest.fn()}
|
||||
onClearSelection={jest.fn()}
|
||||
traceSamples={[]}
|
||||
/>
|
||||
</Wrapper>
|
||||
<TransactionDistribution
|
||||
onChartSelection={jest.fn()}
|
||||
onClearSelection={jest.fn()}
|
||||
traceSamples={[]}
|
||||
/>,
|
||||
|
||||
{ wrapper: Wrapper }
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* 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 type { Meta, Story } from '@storybook/react';
|
||||
import type { CoreStart, DocLinksStart } from 'kibana/public';
|
||||
import React, { ComponentProps } from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { createKibanaReactContext } from '../../../../../../../src/plugins/kibana_react/public';
|
||||
import type { ApmPluginContextValue } from '../../../context/apm_plugin/apm_plugin_context';
|
||||
import { MockApmPluginContextWrapper } from '../../../context/apm_plugin/mock_apm_plugin_context';
|
||||
import { SettingsTemplate } from './settings_template';
|
||||
|
||||
type Args = ComponentProps<typeof SettingsTemplate>;
|
||||
|
||||
const coreMock = {
|
||||
notifications: { toasts: { add: () => {} } },
|
||||
usageCollection: { reportUiCounter: () => {} },
|
||||
observability: {
|
||||
navigation: {
|
||||
PageTemplate: () => {
|
||||
return <>hello world</>;
|
||||
},
|
||||
},
|
||||
},
|
||||
http: {
|
||||
basePath: {
|
||||
prepend: (path: string) => `/basepath${path}`,
|
||||
get: () => `/basepath`,
|
||||
},
|
||||
get: async () => ({}),
|
||||
},
|
||||
docLinks: {
|
||||
DOC_LINK_VERSION: '0',
|
||||
ELASTIC_WEBSITE_URL: 'https://www.elastic.co/',
|
||||
links: {
|
||||
apm: {},
|
||||
observability: { guide: '' },
|
||||
},
|
||||
} as unknown as DocLinksStart,
|
||||
} as unknown as Partial<CoreStart>;
|
||||
|
||||
const KibanaReactContext = createKibanaReactContext(coreMock);
|
||||
|
||||
const stories: Meta<Args> = {
|
||||
title: 'routing/templates/SettingsTemplate',
|
||||
component: SettingsTemplate,
|
||||
decorators: [
|
||||
(StoryComponent) => {
|
||||
return (
|
||||
<MemoryRouter>
|
||||
<KibanaReactContext.Provider>
|
||||
<MockApmPluginContextWrapper
|
||||
value={{ core: coreMock } as unknown as ApmPluginContextValue}
|
||||
>
|
||||
<StoryComponent />
|
||||
</MockApmPluginContextWrapper>
|
||||
</KibanaReactContext.Provider>
|
||||
</MemoryRouter>
|
||||
);
|
||||
},
|
||||
],
|
||||
};
|
||||
export default stories;
|
||||
|
||||
export const Example: Story<Args> = (args) => {
|
||||
return <SettingsTemplate {...args} />;
|
||||
};
|
||||
Example.args = {
|
||||
children: <>test</>,
|
||||
selectedTab: 'agent-configurations',
|
||||
};
|
|
@ -5,69 +5,17 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { render } from '@testing-library/react';
|
||||
import { MockApmPluginContextWrapper } from '../../../context/apm_plugin/mock_apm_plugin_context';
|
||||
import React, { ReactNode } from 'react';
|
||||
import { SettingsTemplate } from './settings_template';
|
||||
import { createMemoryHistory } from 'history';
|
||||
import { MemoryRouter, RouteComponentProps } from 'react-router-dom';
|
||||
import { CoreStart, DocLinksStart, HttpStart } from 'kibana/public';
|
||||
import { createKibanaReactContext } from 'src/plugins/kibana_react/public';
|
||||
import { createCallApmApi } from '../../../services/rest/createCallApmApi';
|
||||
import { composeStories } from '@storybook/testing-react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import * as stories from './settings_template.stories';
|
||||
|
||||
const { location } = createMemoryHistory();
|
||||
|
||||
const KibanaReactContext = createKibanaReactContext({
|
||||
notifications: { toasts: { add: () => {} } },
|
||||
usageCollection: { reportUiCounter: () => {} },
|
||||
observability: {
|
||||
navigation: {
|
||||
PageTemplate: () => {
|
||||
return <>hello world</>;
|
||||
},
|
||||
},
|
||||
},
|
||||
http: {
|
||||
basePath: {
|
||||
prepend: (path: string) => `/basepath${path}`,
|
||||
get: () => `/basepath`,
|
||||
},
|
||||
} as HttpStart,
|
||||
docLinks: {
|
||||
DOC_LINK_VERSION: '0',
|
||||
ELASTIC_WEBSITE_URL: 'https://www.elastic.co/',
|
||||
links: {
|
||||
apm: {},
|
||||
observability: { guide: '' },
|
||||
},
|
||||
} as unknown as DocLinksStart,
|
||||
} as unknown as Partial<CoreStart>);
|
||||
|
||||
function Wrapper({ children }: { children?: ReactNode }) {
|
||||
return (
|
||||
<MemoryRouter>
|
||||
<KibanaReactContext.Provider>
|
||||
<MockApmPluginContextWrapper>{children}</MockApmPluginContextWrapper>
|
||||
</KibanaReactContext.Provider>
|
||||
</MemoryRouter>
|
||||
);
|
||||
}
|
||||
const { Example } = composeStories(stories);
|
||||
|
||||
describe('Settings', () => {
|
||||
beforeEach(() => {
|
||||
createCallApmApi({} as CoreStart);
|
||||
});
|
||||
it('renders', async () => {
|
||||
const routerProps = {
|
||||
location,
|
||||
} as unknown as RouteComponentProps<{}>;
|
||||
expect(() =>
|
||||
render(
|
||||
<SettingsTemplate selectedTab="agent-configurations" {...routerProps}>
|
||||
<div>hello world</div>
|
||||
</SettingsTemplate>,
|
||||
{ wrapper: Wrapper }
|
||||
)
|
||||
).not.toThrowError();
|
||||
render(<Example />);
|
||||
|
||||
expect(await screen.findByText('hello world')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -31,6 +31,12 @@ export const Example: Story<Args> = (args) => {
|
|||
};
|
||||
Example.args = {
|
||||
backendName: 'postgres',
|
||||
query: {
|
||||
environment: 'ENVIRONMENT_ALL',
|
||||
kuery: '',
|
||||
rangeFrom: 'now-15m',
|
||||
rangeTo: 'now',
|
||||
},
|
||||
type: 'db',
|
||||
subtype: 'postgresql',
|
||||
};
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* 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 { composeStories } from '@storybook/testing-react';
|
||||
import { render } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import * as stories from './backend_link.stories';
|
||||
|
||||
const { Example } = composeStories(stories);
|
||||
|
||||
describe('BackendLink', () => {
|
||||
it('renders', () => {
|
||||
expect(() => render(<Example />)).not.toThrowError();
|
||||
});
|
||||
});
|
|
@ -20,18 +20,18 @@ import {
|
|||
ALERT_RULE_UUID,
|
||||
ALERT_RULE_NAME,
|
||||
ALERT_RULE_CATEGORY,
|
||||
ALERT_RULE_CONSUMER,
|
||||
ALERT_RULE_PRODUCER,
|
||||
SPACE_IDS,
|
||||
} from '@kbn/rule-data-utils';
|
||||
import { StoryContext } from '@storybook/react';
|
||||
import React, { ComponentType } from 'react';
|
||||
import { MemoryRouter, Route } from 'react-router-dom';
|
||||
import { Meta, Story } from '@storybook/react';
|
||||
import React from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { KibanaContextProvider } from '../../../../../../../../src/plugins/kibana_react/public';
|
||||
import { ENVIRONMENT_ALL } from '../../../../../common/environment_filter_values';
|
||||
import { LatencyAggregationType } from '../../../../../common/latency_aggregation_types';
|
||||
import {
|
||||
ApmPluginContext,
|
||||
ApmPluginContextValue,
|
||||
} from '../../../../context/apm_plugin/apm_plugin_context';
|
||||
import type { ApmPluginContextValue } from '../../../../context/apm_plugin/apm_plugin_context';
|
||||
import { MockApmPluginContextWrapper } from '../../../../context/apm_plugin/mock_apm_plugin_context';
|
||||
import { APMServiceContext } from '../../../../context/apm_service/apm_service_context';
|
||||
import { ChartPointerEventContextProvider } from '../../../../context/chart_pointer_event/chart_pointer_event_context';
|
||||
import { MockUrlParamsContextProvider } from '../../../../context/url_params_context/mock_url_params_context_provider';
|
||||
|
@ -46,7 +46,7 @@ interface Args {
|
|||
latencyChartResponse: APIReturnType<'GET /internal/apm/services/{serviceName}/transactions/charts/latency'>;
|
||||
}
|
||||
|
||||
export default {
|
||||
const stories: Meta<Args> = {
|
||||
title: 'shared/charts/LatencyChart',
|
||||
component: LatencyChart,
|
||||
argTypes: {
|
||||
|
@ -57,7 +57,7 @@ export default {
|
|||
},
|
||||
},
|
||||
decorators: [
|
||||
(Story: ComponentType, { args }: StoryContext) => {
|
||||
(StoryComponent, { args }) => {
|
||||
const { alertsResponse, latencyChartResponse } = args as Args;
|
||||
const serviceName = 'testService';
|
||||
|
||||
|
@ -88,44 +88,46 @@ export default {
|
|||
const transactionType = `${Math.random()}`; // So we don't memoize
|
||||
|
||||
return (
|
||||
<ApmPluginContext.Provider value={apmPluginContextMock}>
|
||||
<MemoryRouter initialEntries={[`/services/${serviceName}`]}>
|
||||
<Route path="/services/{serviceName}">
|
||||
<KibanaContextProvider
|
||||
services={{ ...apmPluginContextMock.core }}
|
||||
<MemoryRouter
|
||||
initialEntries={[
|
||||
`/services/${serviceName}/overview?environment=ENVIRONMENT_ALL&kuery=&rangeFrom=now-15m&rangeTo=now&transactionType=request&comparisonEnabled=true&comparisonType=day`,
|
||||
]}
|
||||
>
|
||||
<MockApmPluginContextWrapper value={apmPluginContextMock}>
|
||||
<KibanaContextProvider services={{ ...apmPluginContextMock.core }}>
|
||||
<MockUrlParamsContextProvider
|
||||
params={{
|
||||
latencyAggregationType: LatencyAggregationType.avg,
|
||||
}}
|
||||
>
|
||||
<MockUrlParamsContextProvider
|
||||
params={{
|
||||
latencyAggregationType: LatencyAggregationType.avg,
|
||||
<APMServiceContext.Provider
|
||||
value={{
|
||||
alerts: alertsResponse.alerts,
|
||||
serviceName,
|
||||
transactionType,
|
||||
transactionTypes: [],
|
||||
}}
|
||||
>
|
||||
<APMServiceContext.Provider
|
||||
value={{
|
||||
alerts: alertsResponse.alerts,
|
||||
serviceName,
|
||||
transactionType,
|
||||
transactionTypes: [],
|
||||
}}
|
||||
>
|
||||
<ChartPointerEventContextProvider>
|
||||
<Story />
|
||||
</ChartPointerEventContextProvider>
|
||||
</APMServiceContext.Provider>
|
||||
</MockUrlParamsContextProvider>
|
||||
</KibanaContextProvider>
|
||||
</Route>
|
||||
</MemoryRouter>
|
||||
</ApmPluginContext.Provider>
|
||||
<ChartPointerEventContextProvider>
|
||||
<StoryComponent />
|
||||
</ChartPointerEventContextProvider>
|
||||
</APMServiceContext.Provider>
|
||||
</MockUrlParamsContextProvider>
|
||||
</KibanaContextProvider>
|
||||
</MockApmPluginContextWrapper>
|
||||
</MemoryRouter>
|
||||
);
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export function Example(_args: Args) {
|
||||
export default stories;
|
||||
|
||||
export const Example: Story<Args> = () => {
|
||||
return (
|
||||
<LatencyChart height={300} environment={ENVIRONMENT_ALL.value} kuery="" />
|
||||
);
|
||||
}
|
||||
};
|
||||
Example.args = {
|
||||
alertsResponse: {
|
||||
alerts: [
|
||||
|
@ -139,6 +141,7 @@ Example.args = {
|
|||
tags: ['apm', 'service.name:frontend-rum'],
|
||||
'transaction.type': ['page-load'],
|
||||
[ALERT_RULE_PRODUCER]: ['apm'],
|
||||
[ALERT_RULE_CONSUMER]: ['apm'],
|
||||
[ALERT_UUID]: ['af2ae371-df79-4fca-b0eb-a2dbd9478180'],
|
||||
[ALERT_RULE_UUID]: ['82e0ee40-c2f4-11eb-9a42-a9da66a1722f'],
|
||||
'event.action': ['active'],
|
||||
|
@ -149,9 +152,11 @@ Example.args = {
|
|||
[ALERT_START]: ['2021-06-02T04:00:00.000Z'],
|
||||
'event.kind': ['state'],
|
||||
[ALERT_RULE_CATEGORY]: ['Latency threshold'],
|
||||
[SPACE_IDS]: [],
|
||||
},
|
||||
{
|
||||
[ALERT_RULE_TYPE_ID]: ['apm.transaction_duration'],
|
||||
|
||||
[ALERT_EVALUATION_VALUE]: [2001708.19],
|
||||
'service.name': ['frontend-rum'],
|
||||
[ALERT_RULE_NAME]: ['Latency threshold | frontend-rum'],
|
||||
|
@ -160,6 +165,7 @@ Example.args = {
|
|||
tags: ['apm', 'service.name:frontend-rum'],
|
||||
'transaction.type': ['page-load'],
|
||||
[ALERT_RULE_PRODUCER]: ['apm'],
|
||||
[ALERT_RULE_CONSUMER]: ['apm'],
|
||||
[ALERT_SEVERITY]: ['warning'],
|
||||
[ALERT_UUID]: ['af2ae371-df79-4fca-b0eb-a2dbd9478181'],
|
||||
[ALERT_RULE_UUID]: ['82e0ee40-c2f4-11eb-9a42-a9da66a1722f'],
|
||||
|
@ -171,9 +177,11 @@ Example.args = {
|
|||
[ALERT_START]: ['2021-06-02T10:45:00.000Z'],
|
||||
'event.kind': ['state'],
|
||||
[ALERT_RULE_CATEGORY]: ['Latency threshold'],
|
||||
[SPACE_IDS]: [],
|
||||
},
|
||||
{
|
||||
[ALERT_RULE_TYPE_ID]: ['apm.transaction_duration'],
|
||||
|
||||
[ALERT_EVALUATION_VALUE]: [2001708.19],
|
||||
'service.name': ['frontend-rum'],
|
||||
[ALERT_RULE_NAME]: ['Latency threshold | frontend-rum'],
|
||||
|
@ -182,6 +190,7 @@ Example.args = {
|
|||
tags: ['apm', 'service.name:frontend-rum'],
|
||||
'transaction.type': ['page-load'],
|
||||
[ALERT_RULE_PRODUCER]: ['apm'],
|
||||
[ALERT_RULE_CONSUMER]: ['apm'],
|
||||
[ALERT_SEVERITY]: ['critical'],
|
||||
[ALERT_UUID]: ['af2ae371-df79-4fca-b0eb-a2dbd9478182'],
|
||||
[ALERT_RULE_UUID]: ['82e0ee40-c2f4-11eb-9a42-a9da66a1722f'],
|
||||
|
@ -193,6 +202,7 @@ Example.args = {
|
|||
[ALERT_START]: ['2021-06-02T16:50:00.000Z'],
|
||||
'event.kind': ['state'],
|
||||
[ALERT_RULE_CATEGORY]: ['Latency threshold'],
|
||||
[SPACE_IDS]: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -801,19 +811,24 @@ Example.args = {
|
|||
},
|
||||
],
|
||||
},
|
||||
previousPeriod: { latencyTimeseries: [] },
|
||||
previousPeriod: { latencyTimeseries: [], overallAvgDuration: null },
|
||||
},
|
||||
};
|
||||
|
||||
export function NoData(_args: Args) {
|
||||
export const NoData: Story<Args> = () => {
|
||||
return (
|
||||
<LatencyChart height={300} environment={ENVIRONMENT_ALL.value} kuery="" />
|
||||
);
|
||||
}
|
||||
};
|
||||
NoData.args = {
|
||||
alertsResponse: { alerts: [] },
|
||||
latencyChartResponse: {
|
||||
currentPeriod: { latencyTimeseries: [] },
|
||||
previousPeriod: { latencyTimeseries: [] },
|
||||
anomalyTimeseries: {
|
||||
jobId: 'apm-production-00aa-high_mean_transaction_duration',
|
||||
anomalyScore: [],
|
||||
anomalyBoundaries: [],
|
||||
},
|
||||
currentPeriod: { latencyTimeseries: [], overallAvgDuration: null },
|
||||
previousPeriod: { latencyTimeseries: [], overallAvgDuration: null },
|
||||
},
|
||||
};
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* 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 { composeStories } from '@storybook/testing-react';
|
||||
import { render, waitFor } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import * as stories from './latency_chart.stories';
|
||||
|
||||
const { Example } = composeStories(stories);
|
||||
|
||||
describe('LatencyChart', () => {
|
||||
it('renders', async () => {
|
||||
await waitFor(() => {
|
||||
expect(() => render(<Example />)).not.toThrowError();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -31,5 +31,11 @@ export const Example: Story<Args> = (args) => {
|
|||
};
|
||||
Example.args = {
|
||||
agentName: 'java',
|
||||
query: {
|
||||
environment: 'ENVIRONMENT_ALL',
|
||||
kuery: '',
|
||||
rangeFrom: 'now-15m',
|
||||
rangeTo: 'now',
|
||||
},
|
||||
serviceName: 'opbeans-java',
|
||||
};
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* 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 { composeStories } from '@storybook/testing-react';
|
||||
import { render } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import * as stories from './service_link.stories';
|
||||
|
||||
const { Example } = composeStories(stories);
|
||||
|
||||
describe('ServiceLink', () => {
|
||||
it('renders', () => {
|
||||
expect(() => render(<Example />)).not.toThrowError();
|
||||
});
|
||||
});
|
|
@ -6,14 +6,16 @@
|
|||
*/
|
||||
|
||||
import { composeStories } from '@storybook/testing-react';
|
||||
import { render } from '@testing-library/react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import * as stories from './suggestions_select.stories';
|
||||
|
||||
const { Example } = composeStories(stories);
|
||||
|
||||
describe('SuggestionsSelect', () => {
|
||||
it('renders', () => {
|
||||
expect(() => render(<Example />)).not.toThrowError();
|
||||
it('renders', async () => {
|
||||
render(<Example />);
|
||||
|
||||
expect(await screen.findByRole('combobox')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue