mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[8.0] [Uptime] Disable 'Create Rule' button when user doesn't have uptime write permissions [#118404] (#120379) (#121163)
* [Uptime] Disable 'Create Rule' button when user doesn't have uptime write permissions [#118404] (#120379) * [Uptime] Disable 'Create Rule' button when user doesn't have uptime write permissions [#118404] Before this commit, users would be able to open the flyout to create an alert and would end-up seeing an error toast when they tried to save it. This commit will now disable the create alert button when the user doesn't have permissions to write to Uptime. It will also display a helpful tooltip. * [Uptime] Disable "Enable Anomaly Alert" when users can't write to uptime [#118404] This commit causes users not to be able to use the "Enable Anomaly Alert" button within the popover in the monitors screen. That button will now be disabled and contain an informative tooltip whenever users don't have permissions to write to Uptime. We've chosen to take this approach so that we don't have to modify the component which deals with the alert creation, which belongs to another team and that we plan on eventually replacing. Furthermore, this pattern is already used in the logs app. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> * add missing useKibana hook to ML Flyout Container for detecting uptime write permissions Co-authored-by: Lucas F. da Costa <lucas@lucasfcosta.com> Co-authored-by: Lucas Fernandes da Costa <lucas.costa@elastic.co>
This commit is contained in:
parent
742fbe969f
commit
06be872e20
10 changed files with 226 additions and 167 deletions
|
@ -1,124 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Manage ML Job renders without errors 1`] = `
|
||||
<div
|
||||
class="euiPopover euiPopover--anchorDownCenter"
|
||||
>
|
||||
<div
|
||||
class="euiPopover__anchor"
|
||||
>
|
||||
<button
|
||||
aria-label="You can enable anomaly detection job or if job is already there you can manage the job or alert."
|
||||
class="euiButton euiButton--primary euiButton--small euiButton-isDisabled"
|
||||
data-test-subj="uptimeManageMLJobBtn"
|
||||
disabled=""
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="euiButtonContent euiButton__content"
|
||||
>
|
||||
<span
|
||||
class="euiLoadingSpinner euiLoadingSpinner--medium euiButtonContent__spinner"
|
||||
/>
|
||||
<span
|
||||
class="euiButton__text"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Manage ML Job shallow renders without errors 1`] = `
|
||||
<ContextProvider
|
||||
value={
|
||||
Object {
|
||||
"history": Object {
|
||||
"action": "POP",
|
||||
"block": [Function],
|
||||
"canGo": [Function],
|
||||
"createHref": [Function],
|
||||
"entries": Array [
|
||||
Object {
|
||||
"hash": "",
|
||||
"key": "TestKeyForTesting",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
],
|
||||
"go": [Function],
|
||||
"goBack": [Function],
|
||||
"goForward": [Function],
|
||||
"index": 0,
|
||||
"length": 1,
|
||||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"key": "TestKeyForTesting",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
"push": [Function],
|
||||
"replace": [Function],
|
||||
},
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"key": "TestKeyForTesting",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
"match": Object {
|
||||
"isExact": true,
|
||||
"params": Object {},
|
||||
"path": "/",
|
||||
"url": "/",
|
||||
},
|
||||
"staticContext": undefined,
|
||||
}
|
||||
}
|
||||
>
|
||||
<ContextProvider
|
||||
value={
|
||||
Object {
|
||||
"action": "POP",
|
||||
"block": [Function],
|
||||
"canGo": [Function],
|
||||
"createHref": [Function],
|
||||
"entries": Array [
|
||||
Object {
|
||||
"hash": "",
|
||||
"key": "TestKeyForTesting",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
],
|
||||
"go": [Function],
|
||||
"goBack": [Function],
|
||||
"goForward": [Function],
|
||||
"index": 0,
|
||||
"length": 1,
|
||||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"key": "TestKeyForTesting",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
"push": [Function],
|
||||
"replace": [Function],
|
||||
}
|
||||
}
|
||||
>
|
||||
<ManageMLJobComponent
|
||||
hasMLJob={true}
|
||||
onEnableJob={[MockFunction]}
|
||||
onJobDelete={[MockFunction]}
|
||||
/>
|
||||
</ContextProvider>
|
||||
</ContextProvider>
|
||||
`;
|
|
@ -30,6 +30,7 @@ import {
|
|||
isAnomalyAlertDeleting,
|
||||
} from '../../../state/alerts/alerts';
|
||||
import { UptimeEditAlertFlyoutComponent } from '../../common/alerts/uptime_edit_alert_flyout';
|
||||
import { useKibana } from '../../../../../../../src/plugins/kibana_react/public';
|
||||
|
||||
interface Props {
|
||||
hasMLJob: boolean;
|
||||
|
@ -38,6 +39,8 @@ interface Props {
|
|||
}
|
||||
|
||||
export const ManageMLJobComponent = ({ hasMLJob, onEnableJob, onJobDelete }: Props) => {
|
||||
const core = useKibana();
|
||||
|
||||
const [isPopOverOpen, setIsPopOverOpen] = useState(false);
|
||||
|
||||
const [isFlyoutOpen, setIsFlyoutOpen] = useState(false);
|
||||
|
@ -82,6 +85,8 @@ export const ManageMLJobComponent = ({ hasMLJob, onEnableJob, onJobDelete }: Pro
|
|||
</EuiButton>
|
||||
);
|
||||
|
||||
const hasUptimeWrite = core.services.application?.capabilities.uptime?.save ?? false;
|
||||
|
||||
const panels = [
|
||||
{
|
||||
id: 0,
|
||||
|
@ -110,6 +115,10 @@ export const ManageMLJobComponent = ({ hasMLJob, onEnableJob, onJobDelete }: Pro
|
|||
name: labels.ENABLE_ANOMALY_ALERT,
|
||||
'data-test-subj': 'uptimeEnableAnomalyAlertBtn',
|
||||
icon: 'bell',
|
||||
disabled: !hasUptimeWrite,
|
||||
toolTipContent: !hasUptimeWrite
|
||||
? labels.ENABLE_ANOMALY_NO_PERMISSIONS_TOOLTIP
|
||||
: null,
|
||||
onClick: () => {
|
||||
dispatch(setAlertFlyoutType(CLIENT_ALERT_TYPES.DURATION_ANOMALY));
|
||||
dispatch(setAlertFlyoutVisible(true));
|
||||
|
|
|
@ -23,13 +23,12 @@ import {
|
|||
import { MLJobLink } from './ml_job_link';
|
||||
import * as labels from './translations';
|
||||
import { MLFlyoutView } from './ml_flyout';
|
||||
import { ML_JOB_ID } from '../../../../common/constants';
|
||||
import { UptimeRefreshContext, UptimeSettingsContext } from '../../../contexts';
|
||||
import { useGetUrlParams } from '../../../hooks';
|
||||
import { getDynamicSettings } from '../../../state/actions/dynamic_settings';
|
||||
import { useMonitorId } from '../../../hooks';
|
||||
import { kibanaService } from '../../../state/kibana_service';
|
||||
import { toMountPoint } from '../../../../../../../src/plugins/kibana_react/public';
|
||||
import { toMountPoint, useKibana } from '../../../../../../../src/plugins/kibana_react/public';
|
||||
import { CLIENT_ALERT_TYPES } from '../../../../common/constants/alerts';
|
||||
|
||||
interface Props {
|
||||
|
@ -73,6 +72,7 @@ const showMLJobNotification = (
|
|||
};
|
||||
|
||||
export const MachineLearningFlyout: React.FC<Props> = ({ onClose }) => {
|
||||
const core = useKibana();
|
||||
const dispatch = useDispatch();
|
||||
const { data: hasMLJob, error } = useSelector(hasNewMLJobSelector);
|
||||
const isMLJobCreating = useSelector(isMLJobCreatingSelector);
|
||||
|
@ -113,14 +113,14 @@ export const MachineLearningFlyout: React.FC<Props> = ({ onClose }) => {
|
|||
true,
|
||||
hasMLJob.awaitingNodeAssignment
|
||||
);
|
||||
const loadMLJob = (jobId: string) =>
|
||||
dispatch(getExistingMLJobAction.get({ monitorId: monitorId as string }));
|
||||
|
||||
loadMLJob(ML_JOB_ID);
|
||||
|
||||
dispatch(getExistingMLJobAction.get({ monitorId: monitorId as string }));
|
||||
refreshApp();
|
||||
dispatch(setAlertFlyoutType(CLIENT_ALERT_TYPES.DURATION_ANOMALY));
|
||||
dispatch(setAlertFlyoutVisible(true));
|
||||
|
||||
const hasUptimeWrite = core.services.application?.capabilities.uptime?.save ?? false;
|
||||
if (hasUptimeWrite) {
|
||||
dispatch(setAlertFlyoutType(CLIENT_ALERT_TYPES.DURATION_ANOMALY));
|
||||
dispatch(setAlertFlyoutVisible(true));
|
||||
}
|
||||
} else {
|
||||
showMLJobNotification(
|
||||
monitorId as string,
|
||||
|
|
|
@ -6,35 +6,97 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { coreMock } from 'src/core/public/mocks';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { ManageMLJobComponent } from './manage_ml_job';
|
||||
import * as redux from 'react-redux';
|
||||
import { renderWithRouter, shallowWithRouter } from '../../../lib';
|
||||
import { KibanaContextProvider } from '../../../../../../../src/plugins/kibana_react/public';
|
||||
import {
|
||||
render,
|
||||
makeUptimePermissionsCore,
|
||||
forNearestButton,
|
||||
} from '../../../lib/helper/rtl_helpers';
|
||||
import * as labels from './translations';
|
||||
|
||||
const core = coreMock.createStart();
|
||||
describe('Manage ML Job', () => {
|
||||
it('shallow renders without errors', () => {
|
||||
jest.spyOn(redux, 'useSelector').mockReturnValue(true);
|
||||
jest.spyOn(redux, 'useDispatch').mockReturnValue(jest.fn());
|
||||
const makeMlCapabilities = (mlCapabilities?: Partial<{ canDeleteJob: boolean }>) => {
|
||||
return {
|
||||
ml: {
|
||||
mlCapabilities: { data: { capabilities: { canDeleteJob: true, ...mlCapabilities } } },
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const wrapper = shallowWithRouter(
|
||||
<ManageMLJobComponent hasMLJob={true} onEnableJob={jest.fn()} onJobDelete={jest.fn()} />
|
||||
);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
describe('when users have write access to uptime', () => {
|
||||
it('enables the button to create alerts', () => {
|
||||
const { getByText } = render(
|
||||
<ManageMLJobComponent hasMLJob={true} onEnableJob={jest.fn()} onJobDelete={jest.fn()} />,
|
||||
{
|
||||
state: makeMlCapabilities(),
|
||||
core: makeUptimePermissionsCore({ save: true }),
|
||||
}
|
||||
);
|
||||
|
||||
const anomalyDetectionBtn = forNearestButton(getByText)(labels.ANOMALY_DETECTION);
|
||||
expect(anomalyDetectionBtn).toBeInTheDocument();
|
||||
userEvent.click(anomalyDetectionBtn as HTMLElement);
|
||||
|
||||
expect(forNearestButton(getByText)(labels.ENABLE_ANOMALY_ALERT)).toBeEnabled();
|
||||
});
|
||||
|
||||
it('does not display an informative tooltip', async () => {
|
||||
const { getByText, findByText } = render(
|
||||
<ManageMLJobComponent hasMLJob={true} onEnableJob={jest.fn()} onJobDelete={jest.fn()} />,
|
||||
{
|
||||
state: makeMlCapabilities(),
|
||||
core: makeUptimePermissionsCore({ save: true }),
|
||||
}
|
||||
);
|
||||
|
||||
const anomalyDetectionBtn = forNearestButton(getByText)(labels.ANOMALY_DETECTION);
|
||||
expect(anomalyDetectionBtn).toBeInTheDocument();
|
||||
userEvent.click(anomalyDetectionBtn as HTMLElement);
|
||||
|
||||
userEvent.hover(getByText(labels.ENABLE_ANOMALY_ALERT));
|
||||
|
||||
await expect(() =>
|
||||
findByText('You need write access to Uptime to create anomaly alerts.')
|
||||
).rejects.toEqual(expect.anything());
|
||||
});
|
||||
});
|
||||
|
||||
it('renders without errors', () => {
|
||||
jest.spyOn(redux, 'useDispatch').mockReturnValue(jest.fn());
|
||||
jest.spyOn(redux, 'useSelector').mockReturnValue(true);
|
||||
describe("when users don't have write access to uptime", () => {
|
||||
it('disables the button to create alerts', () => {
|
||||
const { getByText } = render(
|
||||
<ManageMLJobComponent hasMLJob={true} onEnableJob={jest.fn()} onJobDelete={jest.fn()} />,
|
||||
{
|
||||
state: makeMlCapabilities(),
|
||||
core: makeUptimePermissionsCore({ save: false }),
|
||||
}
|
||||
);
|
||||
|
||||
const wrapper = renderWithRouter(
|
||||
<KibanaContextProvider
|
||||
services={{ ...core, triggersActionsUi: { getEditAlertFlyout: jest.fn() } }}
|
||||
>
|
||||
<ManageMLJobComponent hasMLJob={true} onEnableJob={jest.fn()} onJobDelete={jest.fn()} />
|
||||
</KibanaContextProvider>
|
||||
);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
const anomalyDetectionBtn = forNearestButton(getByText)(labels.ANOMALY_DETECTION);
|
||||
expect(anomalyDetectionBtn).toBeInTheDocument();
|
||||
userEvent.click(anomalyDetectionBtn as HTMLElement);
|
||||
|
||||
expect(forNearestButton(getByText)(labels.ENABLE_ANOMALY_ALERT)).toBeDisabled();
|
||||
});
|
||||
|
||||
it('displays an informative tooltip', async () => {
|
||||
const { getByText, findByText } = render(
|
||||
<ManageMLJobComponent hasMLJob={true} onEnableJob={jest.fn()} onJobDelete={jest.fn()} />,
|
||||
{
|
||||
state: makeMlCapabilities(),
|
||||
core: makeUptimePermissionsCore({ save: false }),
|
||||
}
|
||||
);
|
||||
|
||||
const anomalyDetectionBtn = forNearestButton(getByText)(labels.ANOMALY_DETECTION);
|
||||
expect(anomalyDetectionBtn).toBeInTheDocument();
|
||||
userEvent.click(anomalyDetectionBtn as HTMLElement);
|
||||
|
||||
userEvent.hover(getByText(labels.ENABLE_ANOMALY_ALERT));
|
||||
|
||||
expect(
|
||||
await findByText('You need read-write access to Uptime to create anomaly alerts.')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -105,6 +105,13 @@ export const ENABLE_ANOMALY_ALERT = i18n.translate(
|
|||
}
|
||||
);
|
||||
|
||||
export const ENABLE_ANOMALY_NO_PERMISSIONS_TOOLTIP = i18n.translate(
|
||||
'xpack.uptime.ml.enableAnomalyDetectionPanel.noPermissionsTooltip',
|
||||
{
|
||||
defaultMessage: 'You need read-write access to Uptime to create anomaly alerts.',
|
||||
}
|
||||
);
|
||||
|
||||
export const DISABLE_ANOMALY_ALERT = i18n.translate(
|
||||
'xpack.uptime.ml.enableAnomalyDetectionPanel.disableAnomalyAlert',
|
||||
{
|
||||
|
|
|
@ -58,7 +58,6 @@ describe('<WaterfallMarkerTrend />', () => {
|
|||
{
|
||||
core: {
|
||||
http: {
|
||||
// @ts-expect-error incomplete implementation for testing purposes
|
||||
basePath: {
|
||||
get: () => BASE_PATH,
|
||||
},
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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 userEvent from '@testing-library/user-event';
|
||||
import {
|
||||
render,
|
||||
forNearestButton,
|
||||
makeUptimePermissionsCore,
|
||||
} from '../../../lib/helper/rtl_helpers';
|
||||
import { ToggleAlertFlyoutButtonComponent } from './toggle_alert_flyout_button';
|
||||
import { ToggleFlyoutTranslations } from './translations';
|
||||
|
||||
describe('ToggleAlertFlyoutButtonComponent', () => {
|
||||
describe('when users have write access to uptime', () => {
|
||||
it('enables the button to create a rule', () => {
|
||||
const { getByText } = render(
|
||||
<ToggleAlertFlyoutButtonComponent setAlertFlyoutVisible={jest.fn()} />,
|
||||
{ core: makeUptimePermissionsCore({ save: true }) }
|
||||
);
|
||||
userEvent.click(getByText('Alerts and rules'));
|
||||
expect(
|
||||
forNearestButton(getByText)(ToggleFlyoutTranslations.openAlertContextPanelLabel)
|
||||
).toBeEnabled();
|
||||
});
|
||||
|
||||
it("does not contain a tooltip explaining why the user can't create alerts", async () => {
|
||||
const { getByText, findByText } = render(
|
||||
<ToggleAlertFlyoutButtonComponent setAlertFlyoutVisible={jest.fn()} />,
|
||||
{ core: makeUptimePermissionsCore({ save: true }) }
|
||||
);
|
||||
userEvent.click(getByText('Alerts and rules'));
|
||||
userEvent.hover(getByText(ToggleFlyoutTranslations.openAlertContextPanelLabel));
|
||||
await expect(() =>
|
||||
findByText('You need read-write access to Uptime to create alerts in this app.')
|
||||
).rejects.toEqual(expect.anything());
|
||||
});
|
||||
});
|
||||
|
||||
describe("when users don't have write access to uptime", () => {
|
||||
it('disables the button to create a rule', () => {
|
||||
const { getByText } = render(
|
||||
<ToggleAlertFlyoutButtonComponent setAlertFlyoutVisible={jest.fn()} />,
|
||||
{ core: makeUptimePermissionsCore({ save: false }) }
|
||||
);
|
||||
userEvent.click(getByText('Alerts and rules'));
|
||||
expect(
|
||||
forNearestButton(getByText)(ToggleFlyoutTranslations.openAlertContextPanelLabel)
|
||||
).toBeDisabled();
|
||||
});
|
||||
|
||||
it("contains a tooltip explaining why users can't create rules", async () => {
|
||||
const { getByText, findByText } = render(
|
||||
<ToggleAlertFlyoutButtonComponent setAlertFlyoutVisible={jest.fn()} />,
|
||||
{ core: makeUptimePermissionsCore({ save: false }) }
|
||||
);
|
||||
userEvent.click(getByText('Alerts and rules'));
|
||||
userEvent.hover(getByText(ToggleFlyoutTranslations.openAlertContextPanelLabel));
|
||||
expect(
|
||||
await findByText('You need read-write access to Uptime to create alerts in this app.')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -14,6 +14,7 @@ import {
|
|||
EuiPopover,
|
||||
} from '@elastic/eui';
|
||||
import React, { useState } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { useKibana } from '../../../../../../../src/plugins/kibana_react/public';
|
||||
import { CLIENT_ALERT_TYPES } from '../../../../common/constants/alerts';
|
||||
|
@ -29,12 +30,22 @@ type Props = ComponentProps & ToggleAlertFlyoutButtonProps;
|
|||
const ALERT_CONTEXT_MAIN_PANEL_ID = 0;
|
||||
const ALERT_CONTEXT_SELECT_TYPE_PANEL_ID = 1;
|
||||
|
||||
const noWritePermissionsTooltipContent = i18n.translate(
|
||||
'xpack.uptime.alertDropdown.noWritePermissions',
|
||||
{
|
||||
defaultMessage: 'You need read-write access to Uptime to create alerts in this app.',
|
||||
}
|
||||
);
|
||||
|
||||
export const ToggleAlertFlyoutButtonComponent: React.FC<Props> = ({
|
||||
alertOptions,
|
||||
setAlertFlyoutVisible,
|
||||
}) => {
|
||||
const [isOpen, setIsOpen] = useState<boolean>(false);
|
||||
const kibana = useKibana();
|
||||
|
||||
const hasUptimeWrite = kibana.services.application?.capabilities.uptime?.save ?? false;
|
||||
|
||||
const monitorStatusAlertContextMenuItem: EuiContextMenuPanelItemDescriptor = {
|
||||
'aria-label': ToggleFlyoutTranslations.toggleMonitorStatusAriaLabel,
|
||||
'data-test-subj': 'xpack.uptime.toggleAlertFlyout',
|
||||
|
@ -108,6 +119,8 @@ export const ToggleAlertFlyoutButtonComponent: React.FC<Props> = ({
|
|||
name: ToggleFlyoutTranslations.openAlertContextPanelLabel,
|
||||
icon: 'bell',
|
||||
panel: ALERT_CONTEXT_SELECT_TYPE_PANEL_ID,
|
||||
toolTipContent: !hasUptimeWrite ? noWritePermissionsTooltipContent : null,
|
||||
disabled: !hasUptimeWrite,
|
||||
},
|
||||
managementContextItem,
|
||||
],
|
||||
|
|
|
@ -15,6 +15,7 @@ import {
|
|||
Nullish,
|
||||
} from '@testing-library/react';
|
||||
import { Router } from 'react-router-dom';
|
||||
import { merge } from 'lodash';
|
||||
import { createMemoryHistory, History } from 'history';
|
||||
import { CoreStart } from 'kibana/public';
|
||||
import { I18nProvider } from '@kbn/i18n-react';
|
||||
|
@ -37,12 +38,16 @@ import { triggersActionsUiMock } from '../../../../triggers_actions_ui/public/mo
|
|||
import { dataPluginMock } from '../../../../../../src/plugins/data/public/mocks';
|
||||
import { UptimeRefreshContextProvider, UptimeStartupPluginsContextProvider } from '../../contexts';
|
||||
|
||||
type DeepPartial<T> = {
|
||||
[P in keyof T]?: DeepPartial<T[P]>;
|
||||
};
|
||||
|
||||
interface KibanaProps {
|
||||
services?: KibanaServices;
|
||||
}
|
||||
|
||||
export interface KibanaProviderOptions<ExtraCore> {
|
||||
core?: Partial<CoreStart> & ExtraCore;
|
||||
core?: DeepPartial<CoreStart> & Partial<ExtraCore>;
|
||||
kibanaProps?: KibanaProps;
|
||||
}
|
||||
|
||||
|
@ -64,7 +69,7 @@ type Url =
|
|||
interface RenderRouterOptions<ExtraCore> extends KibanaProviderOptions<ExtraCore> {
|
||||
history?: History;
|
||||
renderOptions?: Omit<RenderOptions, 'queries'>;
|
||||
state?: Partial<AppState>;
|
||||
state?: Partial<AppState> | DeepPartial<AppState>;
|
||||
url?: Url;
|
||||
}
|
||||
|
||||
|
@ -137,10 +142,8 @@ export function MockKibanaProvider<ExtraCore>({
|
|||
core,
|
||||
kibanaProps,
|
||||
}: MockKibanaProviderProps<ExtraCore>) {
|
||||
const coreOptions = {
|
||||
...mockCore(),
|
||||
...core,
|
||||
};
|
||||
const coreOptions = merge({}, mockCore(), core);
|
||||
|
||||
return (
|
||||
<KibanaContextProvider services={{ ...coreOptions }} {...kibanaProps}>
|
||||
<UptimeRefreshContextProvider>
|
||||
|
@ -185,10 +188,7 @@ export function render<ExtraCore>(
|
|||
url,
|
||||
}: RenderRouterOptions<ExtraCore> = {}
|
||||
) {
|
||||
const testState: AppState = {
|
||||
...mockState,
|
||||
...state,
|
||||
};
|
||||
const testState: AppState = merge({}, mockState, state);
|
||||
|
||||
if (url) {
|
||||
history = getHistoryFromUrl(url);
|
||||
|
@ -233,3 +233,26 @@ export const forNearestButton =
|
|||
noOtherButtonHasText && node.textContent === text && node.tagName.toLowerCase() === 'button'
|
||||
);
|
||||
});
|
||||
|
||||
export const makeUptimePermissionsCore = (
|
||||
permissions: Partial<{
|
||||
'alerting:save': boolean;
|
||||
configureSettings: boolean;
|
||||
save: boolean;
|
||||
show: boolean;
|
||||
}>
|
||||
) => {
|
||||
return {
|
||||
application: {
|
||||
capabilities: {
|
||||
uptime: {
|
||||
'alerting:save': true,
|
||||
configureSettings: true,
|
||||
save: true,
|
||||
show: true,
|
||||
...permissions,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
|
@ -89,3 +89,5 @@ export const journeySelector = ({ journeys }: AppState) => journeys;
|
|||
export const networkEventsSelector = ({ networkEvents }: AppState) => networkEvents;
|
||||
|
||||
export const syntheticsSelector = ({ synthetics }: AppState) => synthetics;
|
||||
|
||||
export const uptimeWriteSelector = (state: AppState) => state;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue