Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Uptime] clear ping state when PingList component in unmounted #88321

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,58 +5,58 @@
*/

import React from 'react';
import { shallowWithIntl } from '@kbn/test/jest';
import { PingList } from './ping_list';
import { Ping, PingsResponse } from '../../../../common/runtime_types';
import { ExpandedRowMap } from '../../overview/monitor_list/types';
import { rowShouldExpand, toggleDetails } from './columns/expand_row';
import * as pingListHook from './use_pings';
import { mockReduxHooks } from '../../../lib/helper/test_helpers';
import { mockDispatch } from '../../../lib/helper/test_helpers';
import { render } from '../../../lib/helper/rtl_helpers';

mockReduxHooks();
mockDispatch();

describe('PingList component', () => {
let response: PingsResponse;
const defaultPings = [
{
docId: 'fewjio21',
timestamp: '2019-01-28T17:47:08.078Z',
error: {
message: 'dial tcp 127.0.0.1:9200: connect: connection refused',
type: 'io',
},
monitor: {
duration: { us: 1430 },
id: 'auto-tcp-0X81440A68E839814F',
ip: '127.0.0.1',
name: '',
status: 'down',
type: 'tcp',
},
},
{
docId: 'fewjoo21',
timestamp: '2019-01-28T17:47:09.075Z',
error: {
message: 'dial tcp 127.0.0.1:9200: connect: connection refused',
type: 'io',
},
monitor: {
duration: { us: 1370 },
id: 'auto-tcp-0X81440A68E839814D',
ip: '255.255.255.0',
name: '',
status: 'down',
type: 'tcp',
},
},
];

beforeAll(() => {
response = {
total: 9231,
pings: [
{
docId: 'fewjio21',
timestamp: '2019-01-28T17:47:08.078Z',
error: {
message: 'dial tcp 127.0.0.1:9200: connect: connection refused',
type: 'io',
},
monitor: {
duration: { us: 1430 },
id: 'auto-tcp-0X81440A68E839814F',
ip: '127.0.0.1',
name: '',
status: 'down',
type: 'tcp',
},
},
{
docId: 'fewjoo21',
timestamp: '2019-01-28T17:47:09.075Z',
error: {
message: 'dial tcp 127.0.0.1:9200: connect: connection refused',
type: 'io',
},
monitor: {
duration: { us: 1370 },
id: 'auto-tcp-0X81440A68E839814D',
ip: '127.0.0.1',
name: '',
status: 'down',
type: 'tcp',
},
},
],
};
const response: PingsResponse = {
total: 9231,
pings: defaultPings,
};

beforeEach(() => {
jest.spyOn(pingListHook, 'usePingsList').mockReturnValue({
...response,
error: undefined,
Expand All @@ -65,9 +65,34 @@ describe('PingList component', () => {
});
});

it('renders sorted list without errors', () => {
const component = shallowWithIntl(<PingList />);
expect(component).toMatchSnapshot();
it('renders loading state when pings are loading', () => {
jest.spyOn(pingListHook, 'usePingsList').mockReturnValue({
pings: [],
total: 0,
error: undefined,
loading: true,
failedSteps: { steps: [], checkGroup: '1-f-4d-4f' },
});
const { getByText } = render(<PingList />);
expect(getByText('Loading ping history')).toBeInTheDocument();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Been doing these all week, it's making the test suites so much nicer.

});

it('renders no pings state when pings are not found', () => {
jest.spyOn(pingListHook, 'usePingsList').mockReturnValue({
pings: [],
total: 0,
error: undefined,
loading: false,
failedSteps: { steps: [], checkGroup: '1-f-4d-4f' },
});
const { getByText } = render(<PingList />);
expect(getByText('No pings found')).toBeInTheDocument();
});

it('renders list without errors', () => {
const { getByText } = render(<PingList />);
expect(getByText(`${response.pings[0].monitor.ip}`)).toBeInTheDocument();
expect(getByText(`${response.pings[1].monitor.ip}`)).toBeInTheDocument();
});

describe('toggleDetails', () => {
Expand Down Expand Up @@ -139,7 +164,7 @@ describe('PingList component', () => {
"us": 1370,
},
"id": "auto-tcp-0X81440A68E839814D",
"ip": "127.0.0.1",
"ip": "255.255.255.0",
"name": "",
"status": "down",
"type": "tcp",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { PingTimestamp } from './columns/ping_timestamp';
import { FailedStep } from './columns/failed_step';
import { usePingsList } from './use_pings';
import { PingListHeader } from './ping_list_header';
import { clearPings } from '../../../state/actions';

export const SpanWithMargin = styled.span`
margin-right: 16px;
Expand Down Expand Up @@ -54,6 +55,12 @@ export const PingList = () => {
Object.keys(expandedRows).filter((e) => !pings.some(({ docId }) => docId === e))
);

useEffect(() => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice simple strategy here, small footprint, runs once. I smoke tested this and it seemed to work great.

return () => {
dispatch(clearPings());
};
}, [dispatch]);

useEffect(() => {
const parsed = JSON.parse(expandedIdsToRemove);
if (parsed.length) {
Expand Down Expand Up @@ -200,6 +207,15 @@ export const PingList = () => {
itemId="docId"
itemIdToExpandedRowMap={expandedRows}
pagination={pagination}
noItemsMessage={
loading
? i18n.translate('xpack.uptime.pingList.pingsLoadingMesssage', {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure who determines what the appropriate content is in these cases. Please let me know if this default content is appropriate or need to be run past product.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think 'Loading pings' might accomplish the same thing. @andrewvc any thought on this copy?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the ticket Paul suggested the more generic Loading history.. could work well, since this is a history table.

defaultMessage: 'Loading ping history',
})
: i18n.translate('xpack.uptime.pingList.pingsUnavailableMessage', {
defaultMessage: 'No pings found',
})
}
onChange={(criteria: any) => {
setPageSize(criteria.page!.size);
setPageIndex(criteria.page!.index);
Expand Down
4 changes: 4 additions & 0 deletions x-pack/plugins/uptime/public/lib/helper/test_helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ export function mockReduxHooks(response?: any) {
jest.spyOn(redux, 'useSelector').mockReturnValue(response);
}

export function mockDispatch() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mocking useSelector was causing issues for me, since this component called on two different selectors, so I am only mocking dispatch. Mocking useSelector is less critical when using the default app state within a mock redux provider, as we are in the new rtl custom render.

jest.spyOn(redux, 'useDispatch').mockReturnValue(jest.fn());
}

export function mockReactRouterDomHooks({ useParamsResponse }: { useParamsResponse: any }) {
jest.spyOn(reactRouterDom, 'useParams').mockReturnValue(useParamsResponse);
}
2 changes: 2 additions & 0 deletions x-pack/plugins/uptime/public/state/actions/ping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
GetPingsParams,
} from '../../../common/runtime_types';

export const clearPings = createAction('CLEAR PINGS');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see some actions use SNAKE_CASE and others just use spaces. Which should I be using, or does it matter?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think largely we are not super strict on the formatting of these since in practice no one sees them or needs to do anything with them.


export const getPingHistogram = createAction<GetPingHistogramParams>('GET_PING_HISTOGRAM');
export const getPingHistogramSuccess = createAction<HistogramResult>('GET_PING_HISTOGRAM_SUCCESS');
export const getPingHistogramFail = createAction<Error>('GET_PING_HISTOGRAM_FAIL');
Expand Down
6 changes: 5 additions & 1 deletion x-pack/plugins/uptime/public/state/reducers/ping_list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import { handleActions, Action } from 'redux-actions';
import { PingsResponse } from '../../../common/runtime_types';
import { getPings, getPingsSuccess, getPingsFail } from '../actions';
import { clearPings, getPings, getPingsSuccess, getPingsFail } from '../actions';

export interface PingListState {
pingList: PingsResponse;
Expand All @@ -26,6 +26,10 @@ type PingListPayload = PingsResponse & Error;

export const pingListReducer = handleActions<PingListState, PingListPayload>(
{
[String(clearPings)]: (state) => ({
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could also be resetPings.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with clearPings.

...state,
...initialState,
}),
[String(getPings)]: (state) => ({
...state,
loading: true,
Expand Down