From 09469b33c4275c6b7aacea68743df24a04d6912d Mon Sep 17 00:00:00 2001 From: Nathan L Smith Date: Wed, 14 Oct 2020 23:09:34 -0500 Subject: [PATCH] Sort service list by TPM if health is not shown (#80447) Fall back to sorting by transactions per minute if the health column is not available. Update the test for the component by moving it, removing snapshots, converting to React Testing Library, converting to TypeScript, and adding new cases for this sorting logic. Fixes #79827. --- .../{__test__ => __fixtures__}/props.json | 5 +- .../ServiceList/__test__/List.test.js | 80 --------- .../__test__/__snapshots__/List.test.js.snap | 153 ------------------ .../app/ServiceOverview/ServiceList/index.tsx | 6 +- .../ServiceList/service_list.test.tsx | 122 ++++++++++++++ 5 files changed, 127 insertions(+), 239 deletions(-) rename x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/{__test__ => __fixtures__}/props.json (89%) delete mode 100644 x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/__test__/List.test.js delete mode 100644 x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/__test__/__snapshots__/List.test.js.snap create mode 100644 x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/service_list.test.tsx diff --git a/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/__test__/props.json b/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/__fixtures__/props.json similarity index 89% rename from x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/__test__/props.json rename to x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/__fixtures__/props.json index 7f24ad8b0d308..2e213c44bccf0 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/__test__/props.json +++ b/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/__fixtures__/props.json @@ -11,10 +11,7 @@ "value": 46.06666666666667, "timeseries": [] }, - "avgResponseTime": null, - "environments": [ - "test" - ] + "environments": ["test"] }, { "serviceName": "opbeans-python", diff --git a/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/__test__/List.test.js b/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/__test__/List.test.js deleted file mode 100644 index 7c306c16cca1f..0000000000000 --- a/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/__test__/List.test.js +++ /dev/null @@ -1,80 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { shallow } from 'enzyme'; -import { ServiceList, SERVICE_COLUMNS } from '../index'; -import props from './props.json'; -import { mockMoment } from '../../../../../utils/testHelpers'; -import { ServiceHealthStatus } from '../../../../../../common/service_health_status'; - -describe('ServiceOverview -> List', () => { - beforeAll(() => { - mockMoment(); - }); - - it('renders empty state', () => { - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); - }); - - it('renders with data', () => { - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); - }); - - it('renders columns correctly', () => { - const service = { - serviceName: 'opbeans-python', - agentName: 'python', - transactionsPerMinute: { - value: 86.93333333333334, - timeseries: [], - }, - errorsPerMinute: { - value: 12.6, - timeseries: [], - }, - avgResponseTime: { - value: 91535.42944785276, - timeseries: [], - }, - environments: ['test'], - }; - const renderedColumns = SERVICE_COLUMNS.map((c) => - c.render(service[c.field], service) - ); - - expect(renderedColumns[0]).toMatchSnapshot(); - }); - - describe('without ML data', () => { - it('does not render health column', () => { - const wrapper = shallow(); - - const columns = wrapper.props().columns; - - expect(columns[0].field).not.toBe('healthStatus'); - }); - }); - - describe('with ML data', () => { - it('renders health column', () => { - const wrapper = shallow( - ({ - ...item, - healthStatus: ServiceHealthStatus.warning, - }))} - /> - ); - - const columns = wrapper.props().columns; - - expect(columns[0].field).toBe('healthStatus'); - }); - }); -}); diff --git a/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/__test__/__snapshots__/List.test.js.snap b/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/__test__/__snapshots__/List.test.js.snap deleted file mode 100644 index e6a9823f3ee28..0000000000000 --- a/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/__test__/__snapshots__/List.test.js.snap +++ /dev/null @@ -1,153 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ServiceOverview -> List renders columns correctly 1`] = ` - -`; - -exports[`ServiceOverview -> List renders empty state 1`] = ` - -`; - -exports[`ServiceOverview -> List renders with data 1`] = ` - -`; diff --git a/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/index.tsx b/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/index.tsx index aa0222582b891..49319f167703c 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/index.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/index.tsx @@ -191,18 +191,20 @@ export function ServiceList({ items, noItemsMessage }: Props) { const columns = displayHealthStatus ? SERVICE_COLUMNS : SERVICE_COLUMNS.filter((column) => column.field !== 'healthStatus'); + const initialSortField = displayHealthStatus + ? 'healthStatus' + : 'transactionsPerMinute'; return ( { // For healthStatus, sort items by healthStatus first, then by TPM - return sortField === 'healthStatus' ? orderBy( itemsToSort, diff --git a/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/service_list.test.tsx b/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/service_list.test.tsx new file mode 100644 index 0000000000000..daddd0a60fe1f --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/service_list.test.tsx @@ -0,0 +1,122 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { ReactNode } from 'react'; +import { MemoryRouter } from 'react-router-dom'; +import { ServiceHealthStatus } from '../../../../../common/service_health_status'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { ServiceListAPIResponse } from '../../../../../server/lib/services/get_services'; +import { MockApmPluginContextWrapper } from '../../../../context/ApmPluginContext/MockApmPluginContext'; +import { mockMoment, renderWithTheme } from '../../../../utils/testHelpers'; +import { ServiceList, SERVICE_COLUMNS } from './'; +import props from './__fixtures__/props.json'; + +function Wrapper({ children }: { children?: ReactNode }) { + return ( + + {children} + + ); +} + +describe('ServiceList', () => { + beforeAll(() => { + mockMoment(); + }); + + it('renders empty state', () => { + expect(() => + renderWithTheme(, { wrapper: Wrapper }) + ).not.toThrowError(); + }); + + it('renders with data', () => { + expect(() => + // Types of property 'avgResponseTime' are incompatible. + // Type 'null' is not assignable to type '{ value: number | null; timeseries: { x: number; y: number | null; }[]; } | undefined'.ts(2322) + renderWithTheme( + , + { wrapper: Wrapper } + ) + ).not.toThrowError(); + }); + + it('renders columns correctly', () => { + const service: any = { + serviceName: 'opbeans-python', + agentName: 'python', + transactionsPerMinute: { + value: 86.93333333333334, + timeseries: [], + }, + errorsPerMinute: { + value: 12.6, + timeseries: [], + }, + avgResponseTime: { + value: 91535.42944785276, + timeseries: [], + }, + environments: ['test'], + }; + const renderedColumns = SERVICE_COLUMNS.map((c) => + c.render!(service[c.field!], service) + ); + + expect(renderedColumns[0]).toMatchInlineSnapshot(` + + `); + }); + + 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 transactions per minute', async () => { + const { findByTitle } = renderWithTheme( + , + { + wrapper: Wrapper, + } + ); + + expect( + await findByTitle('Trans. per minute; Sorted in descending order') + ).toBeInTheDocument(); + }); + }); + + describe('with ML data', () => { + it('renders the health column', async () => { + const { findByTitle } = renderWithTheme( + ({ + ...item, + healthStatus: ServiceHealthStatus.warning, + }) + )} + />, + { wrapper: Wrapper } + ); + + expect( + await findByTitle('Health; Sorted in descending order') + ).toBeInTheDocument(); + }); + }); +});