From 9fce468997e7057cc7140929a751c7598fe1a630 Mon Sep 17 00:00:00 2001 From: Umberto Pepato Date: Mon, 14 Oct 2024 12:50:55 +0200 Subject: [PATCH] [ResponseOps][Alerts] Don't show empty state in grouping component while first loading (#195777) ## Summary Makes the loading state and empty state mutually exclusive in the grouping component to avoid showing the empty state when first loading the groups data. ## To verify 1. Create one or more O11y rules that fire alerts 2. Open the O11y > Alerts page 3. Toggle on grouping 4. Reload the page (possibly after activating network throttling) 5. Verify that while the loading indicator is shown, the empty state is not and viceversa ## References Fixes #190954 (cherry picked from commit 45a9cf0e343e6c4045834968fa27f6f468cdf3e3) --- .../src/components/grouping.test.tsx | 73 +++++++++++-------- .../kbn-grouping/src/components/grouping.tsx | 5 +- 2 files changed, 44 insertions(+), 34 deletions(-) diff --git a/packages/kbn-grouping/src/components/grouping.test.tsx b/packages/kbn-grouping/src/components/grouping.test.tsx index 08aa78da6d10c..c76be444fdd27 100644 --- a/packages/kbn-grouping/src/components/grouping.test.tsx +++ b/packages/kbn-grouping/src/components/grouping.test.tsx @@ -7,41 +7,52 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { fireEvent, render, within } from '@testing-library/react'; +import { fireEvent, render, within, screen } from '@testing-library/react'; import React from 'react'; import { I18nProvider } from '@kbn/i18n-react'; -import { Grouping } from './grouping'; +import { Grouping, GroupingProps } from './grouping'; import { createGroupFilter, getNullGroupFilter } from '../containers/query/helpers'; import { METRIC_TYPE } from '@kbn/analytics'; import { getTelemetryEvent } from '../telemetry/const'; import { mockGroupingProps, host1Name, host2Name } from './grouping.mock'; +import { SetRequired } from 'type-fest'; const renderChildComponent = jest.fn(); const takeActionItems = jest.fn(); const mockTracker = jest.fn(); -const testProps = { +const testProps: SetRequired, 'data'> = { ...mockGroupingProps, renderChildComponent, takeActionItems, tracker: mockTracker, }; -describe('grouping container', () => { +describe('Grouping', () => { beforeEach(() => { jest.clearAllMocks(); }); + it('Renders groups count when groupsCount > 0', () => { - const { getByTestId, getAllByTestId, queryByTestId } = render( + render( ); - expect(getByTestId('unit-count').textContent).toBe('14 events'); - expect(getByTestId('group-count').textContent).toBe('3 groups'); - expect(getAllByTestId('grouping-accordion').length).toBe(3); - expect(queryByTestId('empty-results-panel')).not.toBeInTheDocument(); + expect(screen.getByTestId('unit-count').textContent).toBe('14 events'); + expect(screen.getByTestId('group-count').textContent).toBe('3 groups'); + expect(screen.getAllByTestId('grouping-accordion').length).toBe(3); + expect(screen.queryByTestId('empty-results-panel')).not.toBeInTheDocument(); + }); + + it('Does not render empty state while loading', () => { + render( + + + + ); + expect(screen.queryByTestId('empty-results-panel')).not.toBeInTheDocument(); }); it('Does not render group counts when groupsCount = 0', () => { @@ -58,25 +69,25 @@ describe('grouping container', () => { value: 0, }, }; - const { getByTestId, queryByTestId } = render( + render( ); - expect(queryByTestId('unit-count')).not.toBeInTheDocument(); - expect(queryByTestId('group-count')).not.toBeInTheDocument(); - expect(queryByTestId('grouping-accordion')).not.toBeInTheDocument(); - expect(getByTestId('empty-results-panel')).toBeInTheDocument(); + expect(screen.queryByTestId('unit-count')).not.toBeInTheDocument(); + expect(screen.queryByTestId('group-count')).not.toBeInTheDocument(); + expect(screen.queryByTestId('grouping-accordion')).not.toBeInTheDocument(); + expect(screen.getByTestId('empty-results-panel')).toBeInTheDocument(); }); it('Opens one group at a time when each group is clicked', () => { - const { getAllByTestId } = render( + render( ); - const group1 = within(getAllByTestId('grouping-accordion')[0]).getAllByRole('button')[0]; - const group2 = within(getAllByTestId('grouping-accordion')[1]).getAllByRole('button')[0]; + const group1 = within(screen.getAllByTestId('grouping-accordion')[0]).getAllByRole('button')[0]; + const group2 = within(screen.getAllByTestId('grouping-accordion')[1]).getAllByRole('button')[0]; fireEvent.click(group1); expect(renderChildComponent).toHaveBeenNthCalledWith( 1, @@ -90,12 +101,12 @@ describe('grouping container', () => { }); it('Send Telemetry when each group is clicked', () => { - const { getAllByTestId } = render( + render( ); - const group1 = within(getAllByTestId('grouping-accordion')[0]).getAllByRole('button')[0]; + const group1 = within(screen.getAllByTestId('grouping-accordion')[0]).getAllByRole('button')[0]; fireEvent.click(group1); expect(mockTracker).toHaveBeenNthCalledWith( 1, @@ -120,19 +131,19 @@ describe('grouping container', () => { it('Renders a null group and passes the correct filter to take actions and child component', () => { takeActionItems.mockReturnValue([]); - const { getAllByTestId, getByTestId } = render( + render( ); - expect(getByTestId('null-group-icon')).toBeInTheDocument(); + expect(screen.getByTestId('null-group-icon')).toBeInTheDocument(); - let lastGroup = getAllByTestId('grouping-accordion').at(-1); + let lastGroup = screen.getAllByTestId('grouping-accordion').at(-1); fireEvent.click(within(lastGroup!).getByTestId('take-action-button')); expect(takeActionItems).toHaveBeenCalledWith(getNullGroupFilter('host.name'), 2); - lastGroup = getAllByTestId('grouping-accordion').at(-1); + lastGroup = screen.getAllByTestId('grouping-accordion').at(-1); fireEvent.click(within(lastGroup!).getByTestId('group-panel-toggle')); expect(renderChildComponent).toHaveBeenCalledWith(getNullGroupFilter('host.name')); @@ -149,7 +160,7 @@ describe('grouping container', () => { expect(groupPanelRenderer).toHaveBeenNthCalledWith( 1, 'host.name', - testProps.data.groupByFields.buckets[0], + testProps.data.groupByFields!.buckets![0], undefined, false ); @@ -157,7 +168,7 @@ describe('grouping container', () => { expect(groupPanelRenderer).toHaveBeenNthCalledWith( 2, 'host.name', - testProps.data.groupByFields.buckets[1], + testProps.data.groupByFields!.buckets![1], undefined, false ); @@ -165,7 +176,7 @@ describe('grouping container', () => { expect(groupPanelRenderer).toHaveBeenNthCalledWith( 3, 'host.name', - testProps.data.groupByFields.buckets[2], + testProps.data.groupByFields!.buckets![2], 'The selected group by field, host.name, is missing a value for this group of events.', false ); @@ -181,7 +192,7 @@ describe('grouping container', () => { expect(groupPanelRenderer).toHaveBeenNthCalledWith( 1, 'host.name', - testProps.data.groupByFields.buckets[0], + testProps.data.groupByFields!.buckets![0], undefined, true ); @@ -189,12 +200,12 @@ describe('grouping container', () => { describe('groupsUnit', () => { it('renders default groupsUnit text correctly', () => { - const { getByTestId } = render( + render( ); - expect(getByTestId('group-count').textContent).toBe('3 groups'); + expect(screen.getByTestId('group-count').textContent).toBe('3 groups'); }); it('calls custom groupsUnit callback correctly', () => { // Provide a custom groupsUnit function in testProps @@ -203,14 +214,14 @@ describe('grouping container', () => { ); const customProps = { ...testProps, groupsUnit: customGroupsUnit }; - const { getByTestId } = render( + render( ); expect(customGroupsUnit).toHaveBeenCalledWith(3, testProps.selectedGroup, true); - expect(getByTestId('group-count').textContent).toBe('3 custom units'); + expect(screen.getByTestId('group-count').textContent).toBe('3 custom units'); }); }); }); diff --git a/packages/kbn-grouping/src/components/grouping.tsx b/packages/kbn-grouping/src/components/grouping.tsx index 7fb8a9b9edd0a..36d284cf28df6 100644 --- a/packages/kbn-grouping/src/components/grouping.tsx +++ b/packages/kbn-grouping/src/components/grouping.tsx @@ -222,10 +222,9 @@ const GroupingComponent = ({ css={groupingLevel > 0 ? groupingContainerCssLevel : groupingContainerCss} className="eui-xScroll" > - {isLoading && ( + {isLoading ? ( - )} - {groupCount > 0 ? ( + ) : groupCount > 0 ? ( {groupPanels} {groupCount > 0 && (