mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Synthetics] use_monitor_name - remove public saved object client usage (#158021)
Co-authored-by: shahzad31 <shahzad31comp@gmail.com>
This commit is contained in:
parent
504d2216b2
commit
dc20c71811
16 changed files with 178 additions and 196 deletions
|
@ -60,7 +60,7 @@ import {
|
|||
ThrottlingWrapper,
|
||||
} from './field_wrappers';
|
||||
import { getDocLinks } from '../../../../../kibana_services';
|
||||
import { useMonitorName } from '../hooks/use_monitor_name';
|
||||
import { useMonitorName } from '../../../hooks/use_monitor_name';
|
||||
import {
|
||||
ConfigKey,
|
||||
DataStream,
|
||||
|
|
|
@ -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
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { defaultCore, WrappedHelper } from '../../../utils/testing/rtl_helpers';
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import { useMonitorName } from './use_monitor_name';
|
||||
import { Router, useParams } from 'react-router-dom';
|
||||
|
||||
const mockRouter = {
|
||||
useParams,
|
||||
...Router,
|
||||
};
|
||||
|
||||
jest.mock('react-router-dom', () => ({
|
||||
...jest.requireActual('react-router-dom'),
|
||||
useParams: jest.fn().mockReturnValue({}),
|
||||
}));
|
||||
|
||||
describe('useMonitorName', () => {
|
||||
it('returns expected results', () => {
|
||||
const { result } = renderHook(() => useMonitorName({}), { wrapper: WrappedHelper });
|
||||
|
||||
expect(result.current).toStrictEqual({ nameAlreadyExists: false, validName: '' });
|
||||
expect(defaultCore.savedObjects.client.find).toHaveBeenCalledWith({
|
||||
aggs: {
|
||||
monitorNames: {
|
||||
terms: { field: 'synthetics-monitor.attributes.name.keyword', size: 10000 },
|
||||
},
|
||||
},
|
||||
perPage: 0,
|
||||
type: 'synthetics-monitor',
|
||||
});
|
||||
});
|
||||
|
||||
it('returns expected results after data', async () => {
|
||||
defaultCore.savedObjects.client.find = jest.fn().mockReturnValue({
|
||||
aggregations: {
|
||||
monitorNames: {
|
||||
buckets: [{ key: 'Test' }, { key: 'Test 1' }],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const { result, waitForNextUpdate } = renderHook(() => useMonitorName({ search: 'Test' }), {
|
||||
wrapper: WrappedHelper,
|
||||
});
|
||||
|
||||
expect(result.current).toStrictEqual({ nameAlreadyExists: false, validName: 'Test' });
|
||||
|
||||
await waitForNextUpdate();
|
||||
|
||||
expect(result.current).toStrictEqual({ nameAlreadyExists: true, validName: '' });
|
||||
});
|
||||
|
||||
it('returns expected results after data while editing monitor', async () => {
|
||||
defaultCore.savedObjects.client.find = jest.fn().mockReturnValue({
|
||||
aggregations: {
|
||||
monitorNames: {
|
||||
buckets: [{ key: 'Test' }, { key: 'Test 1' }],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
jest.spyOn(mockRouter, 'useParams').mockReturnValue({ monitorId: 'test-id' });
|
||||
|
||||
const { result, waitForNextUpdate } = renderHook(() => useMonitorName({ search: 'Test' }), {
|
||||
wrapper: WrappedHelper,
|
||||
});
|
||||
|
||||
expect(result.current).toStrictEqual({ nameAlreadyExists: false, validName: 'Test' });
|
||||
|
||||
await waitForNextUpdate();
|
||||
|
||||
expect(result.current).toStrictEqual({ nameAlreadyExists: false, validName: 'Test' });
|
||||
});
|
||||
});
|
|
@ -1,64 +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 { useEffect, useState } from 'react';
|
||||
import { useFetcher } from '@kbn/observability-shared-plugin/public';
|
||||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { syntheticsMonitorType } from '../../../../../../common/types/saved_objects';
|
||||
|
||||
interface AggsResponse {
|
||||
monitorNames: {
|
||||
buckets: Array<{
|
||||
key: string;
|
||||
}>;
|
||||
};
|
||||
}
|
||||
|
||||
export const useMonitorName = ({ search = '' }: { search?: string }) => {
|
||||
const [values, setValues] = useState<string[]>([]);
|
||||
|
||||
const { monitorId } = useParams<{ monitorId: string }>();
|
||||
|
||||
const { savedObjects } = useKibana().services;
|
||||
|
||||
const { data } = useFetcher(() => {
|
||||
const aggs = {
|
||||
monitorNames: {
|
||||
terms: {
|
||||
field: `${syntheticsMonitorType}.attributes.name.keyword`,
|
||||
size: 10000,
|
||||
},
|
||||
},
|
||||
};
|
||||
return savedObjects?.client.find<unknown, typeof aggs>({
|
||||
type: syntheticsMonitorType,
|
||||
perPage: 0,
|
||||
aggs,
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (data?.aggregations) {
|
||||
const newValues = (data.aggregations as AggsResponse)?.monitorNames.buckets.map(({ key }) =>
|
||||
key.toLowerCase()
|
||||
);
|
||||
if (monitorId && newValues.includes(search.toLowerCase())) {
|
||||
setValues(newValues.filter((val) => val !== search.toLowerCase()));
|
||||
} else {
|
||||
setValues(newValues);
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [data, monitorId]);
|
||||
|
||||
const hasMonitor = Boolean(
|
||||
search && values && values.length > 0 && values?.includes(search.trim().toLowerCase())
|
||||
);
|
||||
|
||||
return { nameAlreadyExists: hasMonitor, validName: hasMonitor ? '' : search };
|
||||
};
|
|
@ -17,8 +17,8 @@ import {
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useRecentlyViewedMonitors } from './use_recently_viewed_monitors';
|
||||
import { useMonitorName } from '../../../hooks/use_monitor_name';
|
||||
import { useSelectedLocation } from '../hooks/use_selected_location';
|
||||
import { useMonitorName } from './use_monitor_name';
|
||||
import { AddMonitorLink } from '../../common/links/add_monitor';
|
||||
import { useSyntheticsSettingsContext } from '../../../contexts';
|
||||
|
||||
|
|
|
@ -1,36 +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 { useMemo } from 'react';
|
||||
import { useFetcher } from '@kbn/observability-shared-plugin/public';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { fetchMonitorManagementList } from '../../../state';
|
||||
|
||||
export const useMonitorName = ({ search = '' }: { search?: string }) => {
|
||||
const { data, loading } = useFetcher(() => {
|
||||
return fetchMonitorManagementList({
|
||||
pageSize: 100,
|
||||
pageIndex: 0,
|
||||
sortField: 'name.keyword',
|
||||
sortOrder: 'asc',
|
||||
query: search,
|
||||
});
|
||||
}, [search]);
|
||||
|
||||
const { monitorId } = useParams<{ monitorId: string }>();
|
||||
|
||||
return useMemo(() => {
|
||||
const { monitors = [] } = data ?? {};
|
||||
const values = monitors.map((monitor) => ({
|
||||
label: monitor.attributes.name as string,
|
||||
key: monitor.id,
|
||||
locationIds: monitor.attributes.locations.map((location) => location.id),
|
||||
}));
|
||||
|
||||
return { values: values.filter((val) => val.key !== monitorId), loading };
|
||||
}, [data, loading, monitorId]);
|
||||
};
|
|
@ -11,7 +11,7 @@ import {
|
|||
getSyntheticsFilterDisplayValues,
|
||||
SyntheticsMonitorFilterItem,
|
||||
valueToLabelWithEmptyCount,
|
||||
} from './filter_fields';
|
||||
} from '../../../../utils/filters/filter_fields';
|
||||
import { useGetUrlParams } from '../../../../hooks';
|
||||
import { useMonitorFiltersState } from './use_filters';
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
getSyntheticsFilterDisplayValues,
|
||||
SyntheticsMonitorFilterChangeHandler,
|
||||
LabelWithCountValue,
|
||||
} from './filter_fields';
|
||||
} from '../../../../utils/filters/filter_fields';
|
||||
import { useFilters } from './use_filters';
|
||||
import { FilterButton } from './filter_button';
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
|||
|
||||
import { FilterGroup } from './filter_group';
|
||||
import { SearchField } from '../search_field';
|
||||
import { SyntheticsMonitorFilterChangeHandler } from './filter_fields';
|
||||
import { SyntheticsMonitorFilterChangeHandler } from '../../../../utils/filters/filter_fields';
|
||||
|
||||
export const ListFilters = function ({
|
||||
handleFilterChange,
|
||||
|
|
|
@ -25,7 +25,7 @@ import {
|
|||
getSyntheticsFilterKeyForLabel,
|
||||
SyntheticsMonitorFilterChangeHandler,
|
||||
SyntheticsMonitorFilterField,
|
||||
} from './filter_fields';
|
||||
} from '../../../../utils/filters/filter_fields';
|
||||
|
||||
export const useFilters = (): MonitorFiltersResult | null => {
|
||||
const dispatch = useDispatch();
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
import { useCallback, useEffect, useRef } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useDebounce } from 'react-use';
|
||||
import { useMonitorFiltersState } from '../common/monitor_filters/use_filters';
|
||||
import {
|
||||
fetchMonitorListAction,
|
||||
quietFetchMonitorListAction,
|
||||
|
@ -17,9 +18,8 @@ import {
|
|||
updateManagementPageStateAction,
|
||||
} from '../../../state';
|
||||
import { useSyntheticsRefreshContext } from '../../../contexts';
|
||||
import { useMonitorFiltersState } from '../common/monitor_filters/use_filters';
|
||||
|
||||
export function useMonitorList() {
|
||||
export function useMonitorList(query?: string) {
|
||||
const dispatch = useDispatch();
|
||||
const isInitialMount = useRef(true);
|
||||
|
||||
|
@ -40,11 +40,11 @@ export function useMonitorList() {
|
|||
// Periodically refresh
|
||||
useEffect(() => {
|
||||
if (!isInitialMount.current) {
|
||||
dispatch(quietFetchMonitorListAction(pageState));
|
||||
dispatch(quietFetchMonitorListAction({ ...pageState, query }));
|
||||
}
|
||||
// specifically only want to run this on refreshInterval change
|
||||
// specifically only want to run this on refreshInterval change on query change
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [lastRefresh]);
|
||||
}, [lastRefresh, query]);
|
||||
|
||||
// On initial mount, load the page
|
||||
useDebounce(
|
||||
|
|
|
@ -10,11 +10,11 @@ import { EuiSpacer } from '@elastic/eui';
|
|||
|
||||
import { useSelector } from 'react-redux';
|
||||
import type { useMonitorList } from '../hooks/use_monitor_list';
|
||||
import { selectOverviewStatus } from '../../../state/overview_status';
|
||||
import { MonitorAsyncError } from './monitor_errors/monitor_async_error';
|
||||
import { ListFilters } from '../common/monitor_filters/list_filters';
|
||||
import { MonitorList } from './monitor_list_table/monitor_list';
|
||||
import { MonitorStats } from './monitor_stats/monitor_stats';
|
||||
import { selectOverviewStatus } from '../../../state/overview_status';
|
||||
import { AlertingCallout } from '../../common/alerting_callout/alerting_callout';
|
||||
|
||||
export const MonitorListContainer = ({
|
||||
|
|
|
@ -14,7 +14,7 @@ import { OverviewLoader } from '../overview_loader';
|
|||
import {
|
||||
getSyntheticsFilterDisplayValues,
|
||||
monitorTypeKeyLabelMap,
|
||||
} from '../../../common/monitor_filters/filter_fields';
|
||||
} from '../../../../../utils/filters/filter_fields';
|
||||
import { useFilters } from '../../../common/monitor_filters/use_filters';
|
||||
import { GroupGridItem } from './grid_group_item';
|
||||
import { ConfigKey, MonitorOverviewItem } from '../../../../../../../../common/runtime_types';
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import { WrappedHelper } from '../utils/testing/rtl_helpers';
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import { useMonitorName } from './use_monitor_name';
|
||||
|
||||
jest.mock('react-router-dom', () => ({
|
||||
...jest.requireActual('react-router-dom'),
|
||||
useParams: jest.fn().mockReturnValue({ monitorId: '12345' }),
|
||||
}));
|
||||
|
||||
describe('useMonitorName', () => {
|
||||
const Wrapper = ({ children }: { children: React.ReactElement }) => {
|
||||
return (
|
||||
<WrappedHelper
|
||||
state={{
|
||||
monitorList: {
|
||||
error: null,
|
||||
loading: true,
|
||||
loaded: false,
|
||||
monitorUpsertStatuses: {},
|
||||
data: {
|
||||
absoluteTotal: 1,
|
||||
perPage: 5,
|
||||
page: 1,
|
||||
total: 1,
|
||||
monitors: [
|
||||
{
|
||||
attributes: {
|
||||
name: 'Test monitor name',
|
||||
config_id: '12345',
|
||||
locations: [
|
||||
{
|
||||
id: 'us_central_qa',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
attributes: {
|
||||
name: 'Test monitor name 2',
|
||||
config_id: '12346',
|
||||
locations: [
|
||||
{
|
||||
id: 'us_central_qa',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
syncErrors: [],
|
||||
},
|
||||
pageState: {
|
||||
pageIndex: 1,
|
||||
pageSize: 10,
|
||||
sortOrder: 'asc',
|
||||
sortField: `name.keyword`,
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</WrappedHelper>
|
||||
);
|
||||
};
|
||||
|
||||
it('returns expected results', () => {
|
||||
const { result } = renderHook(() => useMonitorName({}), { wrapper: Wrapper });
|
||||
|
||||
expect(result.current).toStrictEqual({
|
||||
loading: true,
|
||||
values: [
|
||||
{
|
||||
key: '12346',
|
||||
label: 'Test monitor name 2',
|
||||
locationIds: ['us_central_qa'],
|
||||
},
|
||||
],
|
||||
nameAlreadyExists: false,
|
||||
validName: '',
|
||||
});
|
||||
});
|
||||
|
||||
it('returns expected results after data', async () => {
|
||||
const { result } = renderHook(() => useMonitorName({ search: 'Test monitor name 2' }), {
|
||||
wrapper: Wrapper,
|
||||
});
|
||||
|
||||
expect(result.current).toStrictEqual({
|
||||
loading: true,
|
||||
nameAlreadyExists: false,
|
||||
validName: 'Test monitor name 2',
|
||||
values: [
|
||||
{
|
||||
key: '12346',
|
||||
label: 'Test monitor name 2',
|
||||
locationIds: ['us_central_qa'],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('returns expected results after data while editing monitor', async () => {
|
||||
const { result } = renderHook(() => useMonitorName({ search: 'Test monitor name' }), {
|
||||
wrapper: Wrapper,
|
||||
});
|
||||
|
||||
expect(result.current).toStrictEqual({
|
||||
loading: true,
|
||||
nameAlreadyExists: false,
|
||||
validName: 'Test monitor name',
|
||||
values: [
|
||||
{
|
||||
key: '12346',
|
||||
label: 'Test monitor name 2',
|
||||
locationIds: ['us_central_qa'],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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 { useMemo } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useMonitorList } from '../components/monitors_page/hooks/use_monitor_list';
|
||||
|
||||
export const useMonitorName = ({ search = '' }: { search?: string }) => {
|
||||
const { monitorId } = useParams<{ monitorId: string }>();
|
||||
|
||||
const { syntheticsMonitors, loading } = useMonitorList(search);
|
||||
|
||||
return useMemo(() => {
|
||||
const nameAlreadyExists = Boolean(
|
||||
syntheticsMonitors?.some(
|
||||
(monitor) => monitor.name.trim().toLowerCase() === search && monitorId !== monitor.config_id
|
||||
)
|
||||
);
|
||||
|
||||
const values = syntheticsMonitors.map((monitor) => ({
|
||||
label: monitor.name as string,
|
||||
key: monitor.config_id,
|
||||
locationIds: monitor.locations.map((location) => location.id),
|
||||
}));
|
||||
|
||||
return {
|
||||
loading,
|
||||
nameAlreadyExists,
|
||||
validName: nameAlreadyExists ? '' : search,
|
||||
values: values.filter((val) => val.key !== monitorId),
|
||||
};
|
||||
}, [loading, monitorId, syntheticsMonitors, search]);
|
||||
};
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { invert } from 'lodash';
|
||||
import { DataStream, ServiceLocations } from '../../../../../../../common/runtime_types';
|
||||
import { MonitorFilterState } from '../../../../state';
|
||||
import { DataStream, ServiceLocations } from '../../../../../common/runtime_types';
|
||||
import { MonitorFilterState } from '../../state';
|
||||
|
||||
export type SyntheticsMonitorFilterField = keyof Omit<MonitorFilterState, 'query'>;
|
||||
|
|
@ -21,7 +21,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
await kibanaServer.savedObjects.clean({ types: [syntheticsMonitorType] });
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
before(async () => {
|
||||
await kibanaServer.savedObjects.clean({ types: [syntheticsMonitorType] });
|
||||
});
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue