diff --git a/x-pack/plugins/apm/jest.config.js b/x-pack/plugins/apm/jest.config.js index 4fd2e7277694..66b4b164a794 100644 --- a/x-pack/plugins/apm/jest.config.js +++ b/x-pack/plugins/apm/jest.config.js @@ -11,7 +11,10 @@ module.exports = { preset: '@kbn/test', rootDir: path.resolve(__dirname, '../../..'), roots: ['/x-pack/plugins/apm'], - setupFiles: ['/x-pack/plugins/apm/.storybook/jest_setup.js'], + setupFiles: [ + '/x-pack/plugins/apm/jest_setup.js', + '/x-pack/plugins/apm/.storybook/jest_setup.js', + ], coverageDirectory: '/target/kibana-coverage/jest/x-pack/plugins/apm', coverageReporters: ['text', 'html'], collectCoverageFrom: [ diff --git a/x-pack/plugins/apm/jest_setup.js b/x-pack/plugins/apm/jest_setup.js new file mode 100644 index 000000000000..df8ba56cdc1c --- /dev/null +++ b/x-pack/plugins/apm/jest_setup.js @@ -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); +}); diff --git a/x-pack/plugins/apm/public/components/alerting/error_count_alert_trigger/error_count_alert_trigger.stories.tsx b/x-pack/plugins/apm/public/components/alerting/error_count_alert_trigger/error_count_alert_trigger.stories.tsx index d28d3076b21c..38ef94f9c152 100644 --- a/x-pack/plugins/apm/public/components/alerting/error_count_alert_trigger/error_count_alert_trigger.stories.tsx +++ b/x-pack/plugins/apm/public/components/alerting/error_count_alert_trigger/error_count_alert_trigger.stories.tsx @@ -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); + 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 (
diff --git a/x-pack/plugins/apm/public/components/alerting/error_count_alert_trigger/error_count_alert_trigger.test.tsx b/x-pack/plugins/apm/public/components/alerting/error_count_alert_trigger/error_count_alert_trigger.test.tsx index 26c62b10e622..edf3b5b675cc 100644 --- a/x-pack/plugins/apm/public/components/alerting/error_count_alert_trigger/error_count_alert_trigger.test.tsx +++ b/x-pack/plugins/apm/public/components/alerting/error_count_alert_trigger/error_count_alert_trigger.test.tsx @@ -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()).not.toThrowError(); + it('renders', async () => { + render(); + + expect(await screen.findByText('Service')).toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/apm/public/components/app/error_group_overview/List/List.test.tsx b/x-pack/plugins/apm/public/components/app/error_group_overview/List/List.test.tsx deleted file mode 100644 index 12fa1c955ccc..000000000000 --- a/x-pack/plugins/apm/public/components/app/error_group_overview/List/List.test.tsx +++ /dev/null @@ -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( - - - - - , - storeState - ); - - expect(toJson(wrapper)).toMatchSnapshot(); - }); - - it('should render with data', () => { - const wrapper = mount( - - - - - - - - - - ); - - expect(toJson(wrapper)).toMatchSnapshot(); - }); -}); diff --git a/x-pack/plugins/apm/public/components/app/error_group_overview/List/__snapshots__/List.test.tsx.snap b/x-pack/plugins/apm/public/components/app/error_group_overview/List/__snapshots__/List.test.tsx.snap deleted file mode 100644 index ee68630daa46..000000000000 --- a/x-pack/plugins/apm/public/components/app/error_group_overview/List/__snapshots__/List.test.tsx.snap +++ /dev/null @@ -1,1335 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ErrorGroupOverview -> List should render empty state 1`] = ` -
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - -
-
- - - Group ID - - - - - - - - - - Type - - - - - - Error message and culprit - - - - - - - - - - -
-
- - No errors found - -
-
-
-
-`; - -exports[`ErrorGroupOverview -> List should render with data 1`] = ` -.c0 { - font-family: 'Roboto Mono','Consolas','Menlo','Courier',monospace; -} - -.c2 { - max-width: 100%; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.c1 { - max-width: 100%; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.c3 { - font-family: 'Roboto Mono','Consolas','Menlo','Courier',monospace; - font-size: 18px; - max-width: 100%; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.c4 { - font-family: 'Roboto Mono','Consolas','Menlo','Courier',monospace; -} - -
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - Group ID - - - - - - - - - - Type - - - - - - Error message and culprit - - - - - - - - - - -
-
- Group ID - - - - -
- -
-
- Type -
- -
-
- Error message and culprit -
-
-
- - - About to blow up! - - -
- -
- elasticapm.contrib.django.client.capture -
-
-
-
-
-
-
-
- Occurrences -
-
- 75 -
-
-
- Latest occurrence -
-
- - 1337 minutes ago (mocking 1515578797) - -
-
-
- Group ID - - - - -
- -
-
- Type -
- -
-
- Error message and culprit -
-
-
- - - AssertionError: - - -
- -
- opbeans.views.oopsie -
-
-
-
-
-
-
-
- Occurrences -
-
- 75 -
-
-
- Latest occurrence -
-
- - 1337 minutes ago (mocking 1515578797) - -
-
-
- Group ID - - - - -
- -
-
- Type -
- -
-
- Error message and culprit -
-
-
- - - AssertionError: Bad luck! - - -
- -
- opbeans.tasks.update_stats -
-
-
-
-
-
-
-
- Occurrences -
-
- 24 -
-
-
- Latest occurrence -
-
- - 1337 minutes ago (mocking 1515578796) - -
-
-
- Group ID - - - - -
- -
-
- Type -
- -
-
- Error message and culprit -
-
-
- - - Customer with ID 8517 not found - - -
- -
- opbeans.views.customer -
-
-
-
-
-
-
-
- Occurrences -
-
- 15 -
-
-
- Latest occurrence -
-
- - 1337 minutes ago (mocking 1515578773) - -
-
-
-
-
-
-
-
- -
-
-
-
-`; diff --git a/x-pack/plugins/apm/public/components/app/error_group_overview/List/__fixtures__/props.json b/x-pack/plugins/apm/public/components/app/error_group_overview/error_group_list/__fixtures__/props.json similarity index 100% rename from x-pack/plugins/apm/public/components/app/error_group_overview/List/__fixtures__/props.json rename to x-pack/plugins/apm/public/components/app/error_group_overview/error_group_list/__fixtures__/props.json diff --git a/x-pack/plugins/apm/public/components/app/error_group_overview/error_group_list/error_group_list.stories.tsx b/x-pack/plugins/apm/public/components/app/error_group_overview/error_group_list/error_group_list.stories.tsx new file mode 100644 index 000000000000..e61e43c8bb7e --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/error_group_overview/error_group_list/error_group_list.stories.tsx @@ -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; + +const stories: Meta = { + title: 'app/ErrorGroupOverview/ErrorGroupList', + component: ErrorGroupList, + decorators: [ + (StoryComponent) => { + return ( + + + + + + + + ); + }, + ], +}; +export default stories; + +export const Example: Story = (args) => { + return ; +}; +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) => { + return ; +}; +EmptyState.args = { + items: [], + serviceName: 'test service', +}; diff --git a/x-pack/plugins/apm/public/components/app/error_group_overview/error_group_list/error_group_list.test.tsx b/x-pack/plugins/apm/public/components/app/error_group_overview/error_group_list/error_group_list.test.tsx new file mode 100644 index 000000000000..278825c25c68 --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/error_group_overview/error_group_list/error_group_list.test.tsx @@ -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()).not.toThrowError(); + }); +}); diff --git a/x-pack/plugins/apm/public/components/app/error_group_overview/List/index.tsx b/x-pack/plugins/apm/public/components/app/error_group_overview/error_group_list/index.tsx similarity index 100% rename from x-pack/plugins/apm/public/components/app/error_group_overview/List/index.tsx rename to x-pack/plugins/apm/public/components/app/error_group_overview/error_group_list/index.tsx diff --git a/x-pack/plugins/apm/public/components/app/error_group_overview/index.tsx b/x-pack/plugins/apm/public/components/app/error_group_overview/index.tsx index 9020021d3d6f..5e9095def6e5 100644 --- a/x-pack/plugins/apm/public/components/app/error_group_overview/index.tsx +++ b/x-pack/plugins/apm/public/components/app/error_group_overview/index.tsx @@ -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(); diff --git a/x-pack/plugins/apm/public/components/app/service_inventory/service_list/service_list.stories.tsx b/x-pack/plugins/apm/public/components/app/service_inventory/service_list/service_list.stories.tsx new file mode 100644 index 000000000000..628ef4617417 --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/service_inventory/service_list/service_list.stories.tsx @@ -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; + +const coreMock = { + http: { + get: async () => { + return { fallBackToTransactions: false }; + }, + }, + notifications: { toasts: { add: () => {} } }, + uiSettings: { get: () => ({}) }, +} as unknown as CoreStart; + +const KibanaReactContext = createKibanaReactContext(coreMock); + +const stories: Meta = { + title: 'app/ServiceInventory/ServiceList', + component: ServiceList, + decorators: [ + (StoryComponent) => { + return ( + + + + + + + + ); + }, + ], +}; +export default stories; + +export const Example: Story = (args) => { + return ; +}; +Example.args = { + isLoading: false, + items, +}; + +export const EmptyState: Story = (args) => { + return ; +}; +EmptyState.args = { + isLoading: false, + items: [], +}; + +export const WithHealthWarnings: Story = (args) => { + return ; +}; +WithHealthWarnings.args = { + isLoading: false, + items: items.map((item) => ({ + ...item, + healthStatus: ServiceHealthStatus.warning, + })), +}; diff --git a/x-pack/plugins/apm/public/components/app/service_inventory/service_list/service_list.test.tsx b/x-pack/plugins/apm/public/components/app/service_inventory/service_list/service_list.test.tsx index 69ec1e6b1eb9..5068d13d589c 100644 --- a/x-pack/plugins/apm/public/components/app/service_inventory/service_list/service_list.test.tsx +++ b/x-pack/plugins/apm/public/components/app/service_inventory/service_list/service_list.test.tsx @@ -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 ( - - {children} - - ); -} +const { Example, EmptyState, WithHealthWarnings } = composeStories(stories); describe('ServiceList', () => { - beforeAll(() => { - mockMoment(); + it('renders empty state', async () => { + render(); - 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(, { - wrapper: Wrapper, - }) - ).not.toThrowError(); - }); + it('renders with data', async () => { + render(); - it('renders with data', () => { - expect(() => - renderWithTheme(, { - 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( - , - { - wrapper: Wrapper, - } - ); - const healthHeading = queryByText('Health'); - - expect(healthHeading).toBeNull(); - }); - it('sorts by throughput', async () => { - const { findByTitle } = renderWithTheme( - , - { - wrapper: Wrapper, - } - ); + render(); - expect(await findByTitle('Throughput')).toBeInTheDocument(); + expect(await screen.findByTitle('Throughput')).toBeInTheDocument(); }); }); describe('with ML data', () => { it('renders the health column', async () => { - const { findByTitle } = renderWithTheme( - ({ - ...item, - healthStatus: ServiceHealthStatus.warning, - }))} - />, - { wrapper: Wrapper } - ); + render(); - expect(await findByTitle('Health')).toBeInTheDocument(); + expect( + await screen.findByRole('button', { name: /Health/ }) + ).toBeInTheDocument(); }); }); }); diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.test.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.test.tsx index 0e9639de4aa7..acee2a964d1e 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.test.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.test.tsx @@ -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 ( - - - - + + + - {children} - - - - + + {children} + + + + + ); } @@ -93,13 +96,13 @@ describe('transaction_details/distribution', () => { })); render( - - - + , + + { wrapper: Wrapper } ); await waitFor(() => { diff --git a/x-pack/plugins/apm/public/components/routing/templates/settings_template.stories.tsx b/x-pack/plugins/apm/public/components/routing/templates/settings_template.stories.tsx new file mode 100644 index 000000000000..4fc35bf242a4 --- /dev/null +++ b/x-pack/plugins/apm/public/components/routing/templates/settings_template.stories.tsx @@ -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; + +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; + +const KibanaReactContext = createKibanaReactContext(coreMock); + +const stories: Meta = { + title: 'routing/templates/SettingsTemplate', + component: SettingsTemplate, + decorators: [ + (StoryComponent) => { + return ( + + + + + + + + ); + }, + ], +}; +export default stories; + +export const Example: Story = (args) => { + return ; +}; +Example.args = { + children: <>test, + selectedTab: 'agent-configurations', +}; diff --git a/x-pack/plugins/apm/public/components/routing/templates/settings_template.test.tsx b/x-pack/plugins/apm/public/components/routing/templates/settings_template.test.tsx index d52c758909ff..90dbbdf2bc54 100644 --- a/x-pack/plugins/apm/public/components/routing/templates/settings_template.test.tsx +++ b/x-pack/plugins/apm/public/components/routing/templates/settings_template.test.tsx @@ -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); - -function Wrapper({ children }: { children?: ReactNode }) { - return ( - - - {children} - - - ); -} +const { Example } = composeStories(stories); describe('Settings', () => { - beforeEach(() => { - createCallApmApi({} as CoreStart); - }); it('renders', async () => { - const routerProps = { - location, - } as unknown as RouteComponentProps<{}>; - expect(() => - render( - -
hello world
-
, - { wrapper: Wrapper } - ) - ).not.toThrowError(); + render(); + + expect(await screen.findByText('hello world')).toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/apm/public/components/shared/backend_link.stories.tsx b/x-pack/plugins/apm/public/components/shared/backend_link.stories.tsx index 31bc2f230279..500aa983b8b1 100644 --- a/x-pack/plugins/apm/public/components/shared/backend_link.stories.tsx +++ b/x-pack/plugins/apm/public/components/shared/backend_link.stories.tsx @@ -31,6 +31,12 @@ export const Example: Story = (args) => { }; Example.args = { backendName: 'postgres', + query: { + environment: 'ENVIRONMENT_ALL', + kuery: '', + rangeFrom: 'now-15m', + rangeTo: 'now', + }, type: 'db', subtype: 'postgresql', }; diff --git a/x-pack/plugins/apm/public/components/shared/backend_link.test.tsx b/x-pack/plugins/apm/public/components/shared/backend_link.test.tsx new file mode 100644 index 000000000000..683fec3a4172 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/backend_link.test.tsx @@ -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()).not.toThrowError(); + }); +}); diff --git a/x-pack/plugins/apm/public/components/shared/charts/latency_chart/latency_chart.stories.tsx b/x-pack/plugins/apm/public/components/shared/charts/latency_chart/latency_chart.stories.tsx index ad51e66f1959..e1921aca8d9e 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/latency_chart/latency_chart.stories.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/latency_chart/latency_chart.stories.tsx @@ -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 = { 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 ( - - - - + + + - - - - - - - - - - - + + + + + + + + ); }, ], }; -export function Example(_args: Args) { +export default stories; + +export const Example: Story = () => { return ( ); -} +}; 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 = () => { return ( ); -} +}; 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 }, }, }; diff --git a/x-pack/plugins/apm/public/components/shared/charts/latency_chart/latency_chart.test.tsx b/x-pack/plugins/apm/public/components/shared/charts/latency_chart/latency_chart.test.tsx new file mode 100644 index 000000000000..f5f7c87ed22d --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/charts/latency_chart/latency_chart.test.tsx @@ -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()).not.toThrowError(); + }); + }); +}); diff --git a/x-pack/plugins/apm/public/components/shared/service_link.stories.tsx b/x-pack/plugins/apm/public/components/shared/service_link.stories.tsx index f25838a3552f..c50c1911afe7 100644 --- a/x-pack/plugins/apm/public/components/shared/service_link.stories.tsx +++ b/x-pack/plugins/apm/public/components/shared/service_link.stories.tsx @@ -31,5 +31,11 @@ export const Example: Story = (args) => { }; Example.args = { agentName: 'java', + query: { + environment: 'ENVIRONMENT_ALL', + kuery: '', + rangeFrom: 'now-15m', + rangeTo: 'now', + }, serviceName: 'opbeans-java', }; diff --git a/x-pack/plugins/apm/public/components/shared/service_link.test.tsx b/x-pack/plugins/apm/public/components/shared/service_link.test.tsx new file mode 100644 index 000000000000..63311b306e6b --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/service_link.test.tsx @@ -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()).not.toThrowError(); + }); +}); diff --git a/x-pack/plugins/apm/public/components/shared/suggestions_select/suggestions_select.test.tsx b/x-pack/plugins/apm/public/components/shared/suggestions_select/suggestions_select.test.tsx index b1fce1c439f3..629a3f3df47f 100644 --- a/x-pack/plugins/apm/public/components/shared/suggestions_select/suggestions_select.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/suggestions_select/suggestions_select.test.tsx @@ -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()).not.toThrowError(); + it('renders', async () => { + render(); + + expect(await screen.findByRole('combobox')).toBeInTheDocument(); }); });