Skip to content

Commit

Permalink
[Uptime][Monitor Management UI]Add sorting to Monitor Management moni…
Browse files Browse the repository at this point in the history
…tors list table. (#124103)(#121117)

* Adds sorting to Monitor Management monitors list table. Default sorting is 'asc' on the 'name' column.
* Fix column wrapping on monitor list table (Monitor Management UI).

#121117
  • Loading branch information
awahab07 authored Feb 2, 2022
1 parent e5a8cec commit 2c9f8a9
Show file tree
Hide file tree
Showing 11 changed files with 213 additions and 113 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import * as t from 'io-ts';
export const FetchMonitorManagementListQueryArgsType = t.partial({
page: t.number,
perPage: t.number,
sortField: t.string,
sortOrder: t.union([t.literal('desc'), t.literal('asc')]),
search: t.string,
searchFields: t.array(t.string),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ import { spyOnUseFetcher } from '../../../lib/helper/spy_use_fetcher';
import { Actions } from './actions';

describe('<Actions />', () => {
const setRefresh = jest.fn();
const onUpdate = jest.fn();
const useFetcher = spyOnUseFetcher({});

it('navigates to edit monitor flow on edit pencil', () => {
render(<Actions id="test-id" setRefresh={setRefresh} />);
render(<Actions id="test-id" onUpdate={onUpdate} />);

expect(screen.getByLabelText('Edit monitor')).toHaveAttribute(
'href',
Expand All @@ -34,7 +34,7 @@ describe('<Actions />', () => {
useFetcher.mockImplementation(originalUseFetcher);
const deleteMonitor = jest.spyOn(fetchers, 'deleteMonitor');
const id = 'test-id';
render(<Actions id={id} setRefresh={setRefresh} />);
render(<Actions id={id} onUpdate={onUpdate} />);

expect(deleteMonitor).not.toBeCalled();

Expand All @@ -45,11 +45,11 @@ describe('<Actions />', () => {

it('calls set refresh when deletion is successful', () => {
const id = 'test-id';
render(<Actions id={id} setRefresh={setRefresh} />);
render(<Actions id={id} onUpdate={onUpdate} />);

userEvent.click(screen.getByLabelText('Delete monitor'));

expect(setRefresh).toBeCalledWith(true);
expect(onUpdate).toHaveBeenCalled();
});

it('shows loading spinner while waiting for monitor to delete', () => {
Expand All @@ -59,7 +59,7 @@ describe('<Actions />', () => {
status: FETCH_STATUS.LOADING,
refetch: () => {},
});
render(<Actions id={id} setRefresh={setRefresh} />);
render(<Actions id={id} onUpdate={onUpdate} />);

expect(screen.getByLabelText('Deleting monitor...')).toBeInTheDocument();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'

interface Props {
id: string;
setRefresh: React.Dispatch<React.SetStateAction<boolean>>;
isDisabled?: boolean;
onUpdate: () => void;
}

export const Actions = ({ id, setRefresh, isDisabled }: Props) => {
export const Actions = ({ id, onUpdate, isDisabled }: Props) => {
const [isDeleting, setIsDeleting] = useState<boolean>(false);
const { basePath } = useContext(UptimeSettingsContext);

Expand All @@ -46,13 +46,13 @@ export const Actions = ({ id, setRefresh, isDisabled }: Props) => {
toastLifeTimeMs: 3000,
});
} else if (status === FETCH_STATUS.SUCCESS) {
setRefresh(true);
onUpdate();
notifications.toasts.success({
title: <p data-test-subj="uptimeDeleteMonitorSuccess">{MONITOR_DELETE_SUCCESS_LABEL}</p>,
toastLifeTimeMs: 3000,
});
}
}, [setIsDeleting, setRefresh, notifications.toasts, status]);
}, [setIsDeleting, onUpdate, notifications.toasts, status]);

// TODO: Add popovers to icons
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { spyOnUseFetcher } from '../../../lib/helper/spy_use_fetcher';
import { MonitorEnabled } from './monitor_enabled';

describe('<MonitorEnabled />', () => {
const setRefresh = jest.fn();
const onUpdate = jest.fn();
const testMonitor = {
[ConfigKey.MONITOR_TYPE]: DataStream.HTTP,
[ConfigKey.ENABLED]: true,
Expand All @@ -34,7 +34,7 @@ describe('<MonitorEnabled />', () => {
});

it('correctly renders "enabled" state', () => {
render(<MonitorEnabled id="test-id" monitor={testMonitor} setRefresh={setRefresh} />);
render(<MonitorEnabled id="test-id" monitor={testMonitor} onUpdate={onUpdate} />);

const switchButton = screen.getByRole('switch') as HTMLButtonElement;
assertMonitorEnabled(switchButton);
Expand All @@ -45,7 +45,7 @@ describe('<MonitorEnabled />', () => {
<MonitorEnabled
id="test-id"
monitor={{ ...testMonitor, [ConfigKey.ENABLED]: false }}
setRefresh={setRefresh}
onUpdate={onUpdate}
/>
);

Expand All @@ -54,7 +54,7 @@ describe('<MonitorEnabled />', () => {
});

it('toggles on click', () => {
render(<MonitorEnabled id="test-id" monitor={testMonitor} setRefresh={setRefresh} />);
render(<MonitorEnabled id="test-id" monitor={testMonitor} onUpdate={onUpdate} />);

const switchButton = screen.getByRole('switch') as HTMLButtonElement;
userEvent.click(switchButton);
Expand All @@ -70,7 +70,7 @@ describe('<MonitorEnabled />', () => {
refetch: () => {},
});

render(<MonitorEnabled id="test-id" monitor={testMonitor} setRefresh={setRefresh} />);
render(<MonitorEnabled id="test-id" monitor={testMonitor} onUpdate={onUpdate} />);
const switchButton = screen.getByRole('switch') as HTMLButtonElement;
userEvent.click(switchButton);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ import { setMonitor } from '../../../state/api';
interface Props {
id: string;
monitor: SyntheticsMonitor;
setRefresh: React.Dispatch<React.SetStateAction<boolean>>;
onUpdate: () => void;
isDisabled?: boolean;
}

export const MonitorEnabled = ({ id, monitor, setRefresh, isDisabled }: Props) => {
export const MonitorEnabled = ({ id, monitor, onUpdate, isDisabled }: Props) => {
const [isEnabled, setIsEnabled] = useState<boolean | null>(null);

const { notifications } = useKibana();
Expand Down Expand Up @@ -53,7 +53,7 @@ export const MonitorEnabled = ({ id, monitor, setRefresh, isDisabled }: Props) =
),
toastLifeTimeMs: 3000,
});
setRefresh(true);
onUpdate();
}
}, [status]); // eslint-disable-line react-hooks/exhaustive-deps

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,24 @@
* 2.0.
*/

import React from 'react';
import { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import { ConfigKey, DataStream, HTTPFields, ScheduleUnit } from '../../../../common/runtime_types';
import { render } from '../../../lib/helper/rtl_helpers';
import { DataStream, HTTPFields, ScheduleUnit } from '../../../../common/runtime_types';
import { MonitorManagementList } from './monitor_list';
import { MonitorManagementList as MonitorManagementListState } from '../../../state/reducers/monitor_management';
import { MonitorManagementList, MonitorManagementListPageState } from './monitor_list';

describe('<ActionBar />', () => {
const setRefresh = jest.fn();
const setPageSize = jest.fn();
const setPageIndex = jest.fn();
describe('<MonitorManagementList />', () => {
const onUpdate = jest.fn();
const onPageStateChange = jest.fn();
const monitors = [];
for (let i = 0; i < 12; i++) {
monitors.push({
id: `test-monitor-id-${i}`,
attributes: {
name: `test-monitor-${i}`,
enabled: true,
schedule: {
unit: ScheduleUnit.MINUTES,
number: `${i}`,
Expand Down Expand Up @@ -53,13 +53,20 @@ describe('<ActionBar />', () => {
} as MonitorManagementListState,
};

const pageState: MonitorManagementListPageState = {
pageIndex: 1,
pageSize: 10,
sortField: ConfigKey.NAME,
sortOrder: 'asc',
};

it.each(monitors)('navigates to edit monitor flow on edit pencil', (monitor) => {
render(
<MonitorManagementList
setRefresh={setRefresh}
setPageSize={setPageSize}
setPageIndex={setPageIndex}
onUpdate={onUpdate}
onPageStateChange={onPageStateChange}
monitorList={state.monitorManagementList}
pageState={pageState}
/>,
{ state }
);
Expand All @@ -79,10 +86,10 @@ describe('<ActionBar />', () => {
it('handles changing per page', () => {
render(
<MonitorManagementList
setRefresh={setRefresh}
setPageSize={setPageSize}
setPageIndex={setPageIndex}
onUpdate={onUpdate}
onPageStateChange={onPageStateChange}
monitorList={state.monitorManagementList}
pageState={pageState}
/>,
{ state }
);
Expand All @@ -91,23 +98,22 @@ describe('<ActionBar />', () => {

userEvent.click(screen.getByText('10 rows'));

expect(setPageSize).toBeCalledWith(10);
expect(onPageStateChange).toBeCalledWith(expect.objectContaining({ pageSize: 10 }));
});

it('handles refreshing and changing page when navigating to the next page', () => {
render(
it('handles refreshing and changing page when navigating to the next page', async () => {
const { getByTestId } = render(
<MonitorManagementList
setRefresh={setRefresh}
setPageSize={setPageSize}
setPageIndex={setPageIndex}
onUpdate={onUpdate}
onPageStateChange={onPageStateChange}
monitorList={state.monitorManagementList}
pageState={{ ...pageState, pageSize: 3, pageIndex: 1 }}
/>,
{ state }
);

userEvent.click(screen.getByTestId('pagination-button-next'));
userEvent.click(getByTestId('pagination-button-next'));

expect(setPageIndex).toBeCalledWith(2);
expect(setRefresh).toBeCalledWith(true);
expect(onPageStateChange).toBeCalledWith(expect.objectContaining({ pageIndex: 2 }));
});
});
Loading

0 comments on commit 2c9f8a9

Please sign in to comment.