From 0a3259d6792b40390f90cb790f92d51243e21525 Mon Sep 17 00:00:00 2001 From: Virginia Cepeda Date: Thu, 19 Dec 2024 16:40:17 -0300 Subject: [PATCH 01/11] Revert "refactor: move ChooseCheckGroup to page folder (#1021)" This reverts commit cf6789171f353a4839b03486decb5d3f6d7fec02. --- .../FormComponents}/CheckStatusInfo.tsx | 10 +++++++++- src/components/CheckForm/FormLayout/FormSection.tsx | 7 +++++-- src/components/CheckStatusInfo/index.ts | 1 - .../ChooseCheckGroup}/CheckGroupCard.tsx | 5 ++--- .../ChooseCheckGroup/ChooseCheckGroup.test.tsx | 0 .../ChooseCheckGroup/ChooseCheckGroup.tsx | 2 +- .../ChooseCheckGroup}/Protocol.tsx | 0 src/{page => components}/ChooseCheckGroup/index.ts | 0 src/components/NewStatusBadge/NewStatusBadge.tsx | 12 ------------ src/components/NewStatusBadge/index.ts | 1 - src/routing/InitialisedRouter.tsx | 2 +- 11 files changed, 18 insertions(+), 22 deletions(-) rename src/components/{CheckStatusInfo => CheckEditor/FormComponents}/CheckStatusInfo.tsx (76%) delete mode 100644 src/components/CheckStatusInfo/index.ts rename src/{page/ChooseCheckGroup/components => components/ChooseCheckGroup}/CheckGroupCard.tsx (96%) rename src/{page => components}/ChooseCheckGroup/ChooseCheckGroup.test.tsx (100%) rename src/{page => components}/ChooseCheckGroup/ChooseCheckGroup.tsx (97%) rename src/{page/ChooseCheckGroup/components => components/ChooseCheckGroup}/Protocol.tsx (100%) rename src/{page => components}/ChooseCheckGroup/index.ts (100%) delete mode 100644 src/components/NewStatusBadge/NewStatusBadge.tsx delete mode 100644 src/components/NewStatusBadge/index.ts diff --git a/src/components/CheckStatusInfo/CheckStatusInfo.tsx b/src/components/CheckEditor/FormComponents/CheckStatusInfo.tsx similarity index 76% rename from src/components/CheckStatusInfo/CheckStatusInfo.tsx rename to src/components/CheckEditor/FormComponents/CheckStatusInfo.tsx index 57ca1db5f..888584656 100644 --- a/src/components/CheckStatusInfo/CheckStatusInfo.tsx +++ b/src/components/CheckEditor/FormComponents/CheckStatusInfo.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { GrafanaTheme2 } from '@grafana/data'; -import { Icon, Stack, TextLink, useStyles2 } from '@grafana/ui'; +import { Badge, Icon, Stack, TextLink, useStyles2 } from '@grafana/ui'; import { css } from '@emotion/css'; import { CheckStatus } from 'types'; @@ -40,6 +40,14 @@ export const CheckStatusInfo = ({ description, docsLink }: CheckStatusInfoProps) ); }; +export const NewStatusBadge = ({ status, className }: { status: CheckStatus; className?: string }) => { + if (![CheckStatus.EXPERIMENTAL, CheckStatus.PRIVATE_PREVIEW, CheckStatus.PUBLIC_PREVIEW].includes(status)) { + return null; + } + + return ; +}; + const getStyles = (theme: GrafanaTheme2) => ({ infoLink: css({ background: `none`, diff --git a/src/components/CheckForm/FormLayout/FormSection.tsx b/src/components/CheckForm/FormLayout/FormSection.tsx index 84510c585..8aeb076ce 100644 --- a/src/components/CheckForm/FormLayout/FormSection.tsx +++ b/src/components/CheckForm/FormLayout/FormSection.tsx @@ -5,8 +5,11 @@ import { Box, Stack, Text, useStyles2 } from '@grafana/ui'; import { css } from '@emotion/css'; import { CheckFormValues } from 'types'; -import { CheckStatusInfo, type CheckStatusInfoProps } from 'components/CheckStatusInfo'; -import { NewStatusBadge } from 'components/NewStatusBadge'; +import { + CheckStatusInfo, + CheckStatusInfoProps, + NewStatusBadge, +} from 'components/CheckEditor/FormComponents/CheckStatusInfo'; import { FORM_MAX_WIDTH } from './FormLayout'; diff --git a/src/components/CheckStatusInfo/index.ts b/src/components/CheckStatusInfo/index.ts deleted file mode 100644 index a70e5d650..000000000 --- a/src/components/CheckStatusInfo/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { CheckStatusInfo, type CheckStatusInfoProps } from './CheckStatusInfo'; diff --git a/src/page/ChooseCheckGroup/components/CheckGroupCard.tsx b/src/components/ChooseCheckGroup/CheckGroupCard.tsx similarity index 96% rename from src/page/ChooseCheckGroup/components/CheckGroupCard.tsx rename to src/components/ChooseCheckGroup/CheckGroupCard.tsx index 920612210..2bca4901e 100644 --- a/src/page/ChooseCheckGroup/components/CheckGroupCard.tsx +++ b/src/components/ChooseCheckGroup/CheckGroupCard.tsx @@ -10,10 +10,9 @@ import { getRoute } from 'routing/utils'; import { CheckTypeGroupOption } from 'hooks/useCheckTypeGroupOptions'; import { useCheckTypeOptions } from 'hooks/useCheckTypeOptions'; import { useLimits } from 'hooks/useLimits'; -import { Card } from 'components/Card'; -import { CheckStatusInfo } from 'components/CheckStatusInfo'; -import { NewStatusBadge } from 'components/NewStatusBadge'; +import { CheckStatusInfo, NewStatusBadge } from 'components/CheckEditor/FormComponents/CheckStatusInfo'; +import { Card } from '../Card'; import { Protocol } from './Protocol'; export const CheckGroupCard = ({ group }: { group: CheckTypeGroupOption }) => { diff --git a/src/page/ChooseCheckGroup/ChooseCheckGroup.test.tsx b/src/components/ChooseCheckGroup/ChooseCheckGroup.test.tsx similarity index 100% rename from src/page/ChooseCheckGroup/ChooseCheckGroup.test.tsx rename to src/components/ChooseCheckGroup/ChooseCheckGroup.test.tsx diff --git a/src/page/ChooseCheckGroup/ChooseCheckGroup.tsx b/src/components/ChooseCheckGroup/ChooseCheckGroup.tsx similarity index 97% rename from src/page/ChooseCheckGroup/ChooseCheckGroup.tsx rename to src/components/ChooseCheckGroup/ChooseCheckGroup.tsx index 9d3d26b14..51529d4af 100644 --- a/src/page/ChooseCheckGroup/ChooseCheckGroup.tsx +++ b/src/components/ChooseCheckGroup/ChooseCheckGroup.tsx @@ -8,7 +8,7 @@ import { DataTestIds } from 'test/dataTestIds'; import { useCheckTypeGroupOptions } from 'hooks/useCheckTypeGroupOptions'; import { OverLimitAlert } from 'components/OverLimitAlert'; -import { CheckGroupCard } from './components/CheckGroupCard'; +import { CheckGroupCard } from './CheckGroupCard'; export const ChooseCheckGroup = () => { const styles = useStyles2(getStyles); diff --git a/src/page/ChooseCheckGroup/components/Protocol.tsx b/src/components/ChooseCheckGroup/Protocol.tsx similarity index 100% rename from src/page/ChooseCheckGroup/components/Protocol.tsx rename to src/components/ChooseCheckGroup/Protocol.tsx diff --git a/src/page/ChooseCheckGroup/index.ts b/src/components/ChooseCheckGroup/index.ts similarity index 100% rename from src/page/ChooseCheckGroup/index.ts rename to src/components/ChooseCheckGroup/index.ts diff --git a/src/components/NewStatusBadge/NewStatusBadge.tsx b/src/components/NewStatusBadge/NewStatusBadge.tsx deleted file mode 100644 index 5836d5343..000000000 --- a/src/components/NewStatusBadge/NewStatusBadge.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; -import { Badge } from '@grafana/ui'; - -import { CheckStatus } from 'types'; - -export const NewStatusBadge = ({ status, className }: { status: CheckStatus; className?: string }) => { - if (![CheckStatus.EXPERIMENTAL, CheckStatus.PRIVATE_PREVIEW, CheckStatus.PUBLIC_PREVIEW].includes(status)) { - return null; - } - - return ; -}; diff --git a/src/components/NewStatusBadge/index.ts b/src/components/NewStatusBadge/index.ts deleted file mode 100644 index ce021d70c..000000000 --- a/src/components/NewStatusBadge/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { NewStatusBadge } from './NewStatusBadge'; diff --git a/src/routing/InitialisedRouter.tsx b/src/routing/InitialisedRouter.tsx index 487948ef5..7153d02c7 100644 --- a/src/routing/InitialisedRouter.tsx +++ b/src/routing/InitialisedRouter.tsx @@ -9,10 +9,10 @@ import { getUserPermissions } from 'data/permissions'; import { useLimits } from 'hooks/useLimits'; import { QueryParamMap, useNavigation } from 'hooks/useNavigation'; import { useQuery } from 'hooks/useQuery'; +import { ChooseCheckGroup } from 'components/ChooseCheckGroup'; import { SceneRedirecter } from 'components/SceneRedirecter'; import { AlertingPage } from 'page/AlertingPage'; import { CheckList } from 'page/CheckList'; -import { ChooseCheckGroup } from 'page/ChooseCheckGroup'; import { ConfigPageLayout } from 'page/ConfigPageLayout'; import { AccessTokensTab } from 'page/ConfigPageLayout/tabs/AccessTokensTab'; import { GeneralTab } from 'page/ConfigPageLayout/tabs/GeneralTab'; From 3cc87fdb48b014eaf9cc33c714333173c44c25f8 Mon Sep 17 00:00:00 2001 From: Virginia Cepeda Date: Thu, 19 Dec 2024 16:40:39 -0300 Subject: [PATCH 02/11] Revert "Feat: Add RBAC to Synthetic Monitoring (#982)" This reverts commit a41e15f093770d525c1be24ef2097fe86a0dfcc4. --- .../AddNewCheckButton/AddNewCheckButton.tsx | 15 +- src/components/AppInitializer.tsx | 15 +- src/components/CheckForm/CheckForm.tsx | 7 +- src/components/ConfigActions.test.tsx | 61 ++++++ src/components/ConfigActions.tsx | 59 +++++ .../DeleteProbeButton/DeleteProbeButton.tsx | 10 +- src/components/LinkedDatasourceView.tsx | 7 +- src/components/ProbeCard/ProbeCard.test.tsx | 14 +- src/components/ProbeCard/ProbeCard.tsx | 6 +- .../ProbeEditor/ProbeEditor.test.tsx | 14 +- src/components/ProbeEditor/ProbeEditor.tsx | 8 +- .../ProbeStatus/ProbeStatus.test.tsx | 10 +- src/components/ProbeStatus/ProbeStatus.tsx | 6 +- .../PluginConfigPage/PluginConfigPage.tsx | 10 +- src/data/permissions.ts | 56 ----- src/datasource/plugin.json | 10 +- src/hooks/useAlertAccessControl.ts | 18 -- src/hooks/useCanEditProbe.ts | 11 +- src/hooks/useDSPermission.ts | 16 ++ src/hooks/usePluginPermissionsCanWrite.ts | 8 - src/page/AlertingPage.tsx | 36 ++- src/page/CheckList/components/BulkActions.tsx | 24 +- .../components/CheckItemActionButtons.tsx | 11 +- .../CheckList/components/CheckListHeader.tsx | 18 +- .../tabs/AccessTokensTab.test.tsx | 39 +--- .../ConfigPageLayout/tabs/AccessTokensTab.tsx | 16 +- src/page/ConfigPageLayout/tabs/GeneralTab.tsx | 4 +- .../ConfigPageLayout/tabs/TerraformTab.tsx | 15 -- src/page/ContactAdminAlert.tsx | 46 ---- .../EditCheck/__tests__/EditCheck.test.tsx | 10 +- src/page/EditProbe/EditProbe.tsx | 14 +- src/page/Probes/Probes.tsx | 6 +- src/page/SubsectionWelcomePage.tsx | 6 +- src/page/UnauthorizedPage.tsx | 16 -- src/plugin.json | 207 +----------------- src/routing/InitialisedRouter.tsx | 41 +--- src/scenes/Common/editButton.tsx | 6 +- src/test/fixtures/rbacPermissions.ts | 44 ---- src/test/mocks/@grafana/runtime.tsx | 3 +- src/test/utils.ts | 85 +------ src/types.ts | 11 - 41 files changed, 258 insertions(+), 761 deletions(-) create mode 100644 src/components/ConfigActions.test.tsx create mode 100644 src/components/ConfigActions.tsx delete mode 100644 src/data/permissions.ts delete mode 100644 src/hooks/useAlertAccessControl.ts delete mode 100644 src/hooks/usePluginPermissionsCanWrite.ts delete mode 100644 src/page/ContactAdminAlert.tsx delete mode 100644 src/page/UnauthorizedPage.tsx delete mode 100644 src/test/fixtures/rbacPermissions.ts diff --git a/src/components/AddNewCheckButton/AddNewCheckButton.tsx b/src/components/AddNewCheckButton/AddNewCheckButton.tsx index 7134d065d..91726af41 100644 --- a/src/components/AddNewCheckButton/AddNewCheckButton.tsx +++ b/src/components/AddNewCheckButton/AddNewCheckButton.tsx @@ -2,20 +2,19 @@ import React from 'react'; import { Button } from '@grafana/ui'; import { ROUTES } from 'routing/types'; -import { getUserPermissions } from 'data/permissions'; +import { useCanWriteSM } from 'hooks/useDSPermission'; import { useNavigation } from 'hooks/useNavigation'; export function AddNewCheckButton() { const navigate = useNavigation(); - const { canWriteChecks } = getUserPermissions(); + const canEdit = useCanWriteSM(); + + if (!canEdit) { + return null; + } return ( - ); diff --git a/src/components/AppInitializer.tsx b/src/components/AppInitializer.tsx index 26e801119..c4d894708 100644 --- a/src/components/AppInitializer.tsx +++ b/src/components/AppInitializer.tsx @@ -6,11 +6,9 @@ import { DataTestIds } from 'test/dataTestIds'; import { hasGlobalPermission } from 'utils'; import { ROUTES } from 'routing/types'; -import { getUserPermissions } from 'data/permissions'; import { useAppInitializer } from 'hooks/useAppInitializer'; import { useMeta } from 'hooks/useMeta'; import { MismatchedDatasourceModal } from 'components/MismatchedDatasourceModal'; -import { ContactAdminAlert } from 'page/ContactAdminAlert'; interface Props { redirectTo?: ROUTES; @@ -21,10 +19,7 @@ interface Props { export const AppInitializer = ({ redirectTo, buttonText }: PropsWithChildren) => { const { jsonData } = useMeta(); const styles = useStyles2(getStyles); - const { canWritePlugin } = getUserPermissions(); - - const canReadDs = hasGlobalPermission(`datasources:read`); - const canInitialize = canWritePlugin && hasGlobalPermission(`datasources:create`); + const canInitialize = hasGlobalPermission(`datasources:create`); const { error, @@ -40,13 +35,11 @@ export const AppInitializer = ({ redirectTo, buttonText }: PropsWithChildren; - } - if (!canInitialize) { return ( - + + Contact your administrator to get you started. + ); } diff --git a/src/components/CheckForm/CheckForm.tsx b/src/components/CheckForm/CheckForm.tsx index 32fbd00ac..1e063c2d2 100644 --- a/src/components/CheckForm/CheckForm.tsx +++ b/src/components/CheckForm/CheckForm.tsx @@ -12,10 +12,9 @@ import { createNavModel } from 'utils'; import { ROUTES } from 'routing/types'; import { generateRoutePath } from 'routing/utils'; import { AdHocCheckResponse } from 'datasource/responses.types'; -import { getUserPermissions } from 'data/permissions'; import { useCheckTypeGroupOption } from 'hooks/useCheckTypeGroupOptions'; import { useCheckTypeOptions } from 'hooks/useCheckTypeOptions'; -import { useCanReadLogs } from 'hooks/useDSPermission'; +import { useCanReadLogs, useCanWriteSM } from 'hooks/useDSPermission'; import { useLimits } from 'hooks/useLimits'; import { toFormValues } from 'components/CheckEditor/checkFormTransformations'; import { CheckJobName } from 'components/CheckEditor/FormComponents/CheckJobName'; @@ -74,7 +73,7 @@ type CheckFormProps = { }; export const CheckForm = ({ check, disabled }: CheckFormProps) => { - const { canWriteChecks } = getUserPermissions(); + const canEdit = useCanWriteSM(); const canReadLogs = useCanReadLogs(); const [openTestCheckModal, setOpenTestCheckModal] = useState(false); const [adhocTestData, setAdhocTestData] = useState(); @@ -92,7 +91,7 @@ export const CheckForm = ({ check, disabled }: CheckFormProps) => { isOverCheckLimit || (checkType === CheckType.Browser && isOverBrowserLimit) || ([CheckType.MULTI_HTTP, CheckType.Scripted].includes(checkType) && isOverScriptedLimit); - const isDisabled = disabled || !canWriteChecks || getLimitDisabled({ isExistingCheck, isLoading, overLimit }); + const isDisabled = disabled || !canEdit || getLimitDisabled({ isExistingCheck, isLoading, overLimit }); const formMethods = useForm({ defaultValues: toFormValues(initialCheck, checkType), diff --git a/src/components/ConfigActions.test.tsx b/src/components/ConfigActions.test.tsx new file mode 100644 index 000000000..514290f93 --- /dev/null +++ b/src/components/ConfigActions.test.tsx @@ -0,0 +1,61 @@ +import React from 'react'; +import { screen } from '@testing-library/react'; +import { render } from 'test/render'; + +import { hasGlobalPermission } from 'utils'; +import { ConfigActions } from 'components/ConfigActions'; + +jest.mock('utils', () => { + return { + ...jest.requireActual('utils'), + hasGlobalPermission: jest.fn().mockReturnValue(true), + }; +}); + +it('shows disable option when activated', async () => { + render(); + + const disableButton = await screen.findByText('Disable synthetic monitoring'); + expect(disableButton).toBeInTheDocument(); +}); + +it('shows enable action when disabled', async () => { + render(, { + meta: { + enabled: false, + }, + }); + + const enableButton = await screen.findByText('Enable plugin'); + expect(enableButton).toBeInTheDocument(); +}); + +it('shows setup action when not intialized', async () => { + render(); + const setupButton = await screen.findByText('Setup'); + expect(setupButton).toBeInTheDocument(); +}); + +it(`doesn't show any config actions when the user doesn't have write permissions`, async () => { + jest.mocked(hasGlobalPermission).mockReturnValue(false); + + render(); + + expect(screen.queryByText('Disable synthetic monitoring')).not.toBeInTheDocument(); + expect(screen.queryByText('Enable plugin')).not.toBeInTheDocument(); + expect(screen.queryByText('Setup')).not.toBeInTheDocument(); +}); + +it(`doesn't show any config actions when the user doesn't have write permissions and meta enabled is false`, async () => { + jest.mocked(hasGlobalPermission).mockReturnValue(false); + + render(, { + meta: { + enabled: false, + }, + }); + + expect(screen.queryByText('Disable synthetic monitoring')).not.toBeInTheDocument(); + expect(screen.queryByText('Enable plugin')).not.toBeInTheDocument(); + expect(screen.queryByText('Setup')).not.toBeInTheDocument(); +}); diff --git a/src/components/ConfigActions.tsx b/src/components/ConfigActions.tsx new file mode 100644 index 000000000..17ad11ad2 --- /dev/null +++ b/src/components/ConfigActions.tsx @@ -0,0 +1,59 @@ +import React, { useState } from 'react'; +import { getBackendSrv } from '@grafana/runtime'; +import { Button, LinkButton } from '@grafana/ui'; + +import { hasGlobalPermission } from 'utils'; +import { ROUTES } from 'routing/types'; +import { getRoute } from 'routing/utils'; +import { useMeta } from 'hooks/useMeta'; + +import { DisablePluginModal } from './DisablePluginModal'; + +export const ConfigActions = ({ initialized }: { initialized?: boolean }) => { + const [showDisableModal, setShowDisableModal] = useState(false); + const meta = useMeta(); + const canEdit = hasGlobalPermission(`plugins:write`); + + const handleEnable = async () => { + await getBackendSrv() + .fetch({ + url: `/api/plugins/${meta.id}/settings`, + method: 'POST', + data: { + enabled: true, + pinned: true, + }, + }) + .toPromise(); + window.location.reload(); + }; + + if (!canEdit) { + return null; + } + + if (!meta.enabled) { + return ( + + ); + } + + if (initialized) { + return ( + <> + + setShowDisableModal(false)} /> + + ); + } + + return ( + + Setup + + ); +}; diff --git a/src/components/DeleteProbeButton/DeleteProbeButton.tsx b/src/components/DeleteProbeButton/DeleteProbeButton.tsx index 13e930873..2910201b5 100644 --- a/src/components/DeleteProbeButton/DeleteProbeButton.tsx +++ b/src/components/DeleteProbeButton/DeleteProbeButton.tsx @@ -19,10 +19,8 @@ export function DeleteProbeButton({ probe, onDeleteSuccess: _onDeleteSuccess }: }, [_onDeleteSuccess]); const { mutateAsync: deleteProbe, isPending } = useDeleteProbe({ onSuccess: onDeleteSuccess }); - - const { canDeleteProbes } = useCanEditProbe(); - - const canDelete = canDeleteProbes && !probe.checks.length; + const canEdit = useCanEditProbe(probe); + const canDelete = canEdit && !probe.checks.length; const styles = getStyles(); const [error, setError] = useState(); @@ -39,7 +37,7 @@ export function DeleteProbeButton({ probe, onDeleteSuccess: _onDeleteSuccess }: }; if (!canDelete) { - const tooltipContent = canDeleteProbes ? ( + const tooltipContent = canEdit ? ( <> Unable to delete the probe because it is currently in use.
@@ -55,7 +53,7 @@ export function DeleteProbeButton({ probe, onDeleteSuccess: _onDeleteSuccess }: // Both tooltip component and button prob is used for accessibility reasons return ( - + diff --git a/src/components/LinkedDatasourceView.tsx b/src/components/LinkedDatasourceView.tsx index 0d2d7e803..e9b32b381 100644 --- a/src/components/LinkedDatasourceView.tsx +++ b/src/components/LinkedDatasourceView.tsx @@ -1,8 +1,7 @@ import React from 'react'; import { Alert, Card, Tag } from '@grafana/ui'; -import { getUserPermissions } from 'data/permissions'; -import { useCanWriteLogs, useCanWriteMetrics } from 'hooks/useDSPermission'; +import { useCanWriteLogs, useCanWriteMetrics, useCanWriteSM } from 'hooks/useDSPermission'; import { useLogsDS } from 'hooks/useLogsDS'; import { useMetricsDS } from 'hooks/useMetricsDS'; import { useSMDS } from 'hooks/useSMDS'; @@ -16,14 +15,14 @@ export const LinkedDatasourceView = ({ type }: LinkedDatasourceViewProps) => { const logsDS = useLogsDS(); const smDS = useSMDS(); - const { canWriteSM } = getUserPermissions(); + const canEditSM = useCanWriteSM(); const canEditLogs = useCanWriteLogs(); const canEditMetrics = useCanWriteMetrics(); const canEditMap = { prometheus: canEditMetrics, loki: canEditLogs, - 'synthetic-monitoring-datasource': canWriteSM, + 'synthetic-monitoring-datasource': canEditSM, }; const dsMap = { diff --git a/src/components/ProbeCard/ProbeCard.test.tsx b/src/components/ProbeCard/ProbeCard.test.tsx index 5e9aabd39..7e7c818fb 100644 --- a/src/components/ProbeCard/ProbeCard.test.tsx +++ b/src/components/ProbeCard/ProbeCard.test.tsx @@ -6,7 +6,7 @@ import { userEvent } from '@testing-library/user-event'; import { DataTestIds } from 'test/dataTestIds'; import { OFFLINE_PROBE, ONLINE_PROBE, PRIVATE_PROBE, PUBLIC_PROBE } from 'test/fixtures/probes'; import { render } from 'test/render'; -import { probeToExtendedProbe, runTestAsRBACReader, runTestAsViewer } from 'test/utils'; +import { probeToExtendedProbe, runTestAsViewer } from 'test/utils'; import { type ExtendedProbe } from 'types'; import { ROUTES } from 'routing/types'; @@ -92,18 +92,6 @@ it(`Displays the correct information for a private probe as a viewer`, async () expect(button).toHaveTextContent('View'); }); -it(`Displays the correct information for a private probe as a RBAC viewer`, async () => { - runTestAsRBACReader(); - const probe = probeToExtendedProbe(PRIVATE_PROBE); - - render(); - await screen.findByText(probe.name, { exact: false }); - - const button = screen.getByTestId('probe-card-action-button'); - expect(button).toBeInTheDocument(); - expect(button).toHaveTextContent('View'); -}); - it(`Displays the correct information for a public probe`, async () => { const probe = probeToExtendedProbe(PUBLIC_PROBE); diff --git a/src/components/ProbeCard/ProbeCard.tsx b/src/components/ProbeCard/ProbeCard.tsx index 6824d5561..0e81c3de1 100644 --- a/src/components/ProbeCard/ProbeCard.tsx +++ b/src/components/ProbeCard/ProbeCard.tsx @@ -15,8 +15,8 @@ import { ProbeLabels } from './ProbeLabels'; import { ProbeStatus } from './ProbeStatus'; export const ProbeCard = ({ probe }: { probe: ExtendedProbe }) => { - const { canWriteProbes } = useCanEditProbe(probe); - const probeEditHref = generateRoutePath(canWriteProbes ? ROUTES.EditProbe : ROUTES.ViewProbe, { id: probe.id! }); + const canEdit = useCanEditProbe(probe); + const probeEditHref = generateRoutePath(canEdit ? ROUTES.EditProbe : ROUTES.ViewProbe, { id: probe.id! }); const labelsString = labelsToString(probe.labels); const styles = useStyles2(getStyles2); @@ -55,7 +55,7 @@ export const ProbeCard = ({ probe }: { probe: ExtendedProbe }) => { - {canWriteProbes ? ( + {canEdit ? ( <> { await assertUneditable(); }); -it('the form is uneditable when logged in as a RBAC viewer', async () => { - runTestAsRBACReader(); - await renderProbeEditor(); - await assertUneditable(); -}); - it('the form actions are unavailable when viewing a public probe', async () => { await renderProbeEditor({ probe: PUBLIC_PROBE }); await assertNoActions(); @@ -130,12 +124,6 @@ it('should render the form in read mode when passing `forceReadMode`', async () await assertUneditable(); }); -it('the form actions are unavailable as a RBAC viewer', async () => { - runTestAsRBACReader(); - await renderProbeEditor(); - await assertNoActions(); -}); - async function assertUneditable() { const nameInput = await screen.findByLabelText('Probe Name', { exact: false }); expect(nameInput).toBeDisabled(); diff --git a/src/components/ProbeEditor/ProbeEditor.tsx b/src/components/ProbeEditor/ProbeEditor.tsx index a13e41874..4a91e7508 100644 --- a/src/components/ProbeEditor/ProbeEditor.tsx +++ b/src/components/ProbeEditor/ProbeEditor.tsx @@ -36,8 +36,8 @@ export const ProbeEditor = ({ forceViewMode, // When true, the form is in view mode }: ProbeEditorProps) => { const styles = useStyles2(getStyles); - const { canWriteProbes } = useCanEditProbe(probe); - const writeMode = canWriteProbes && !forceViewMode; + const canEdit = useCanEditProbe(probe); + const writeMode = canEdit && !forceViewMode; const form = useForm({ defaultValues: probe, resolver: zodResolver(ProbeSchema) }); const { latitude, longitude } = form.watch(); const handleSubmit = form.handleSubmit((formValues: Probe) => onSubmit(formValues)); @@ -164,7 +164,7 @@ export const ProbeEditor = ({ /> - {canWriteProbes && disabled={!writeMode} labelDestination={'probe'} />} + {canEdit && disabled={!writeMode} labelDestination={'probe'} />}
Capabilities
- {canWriteProbes && ( + {canEdit && ( <>
- {canWriteProbes && ( + {canEdit && ( @@ -118,17 +109,12 @@ const AlertingPageContent = () => { key={`${alertRule.alert}-${index}`} rule={alertRule} onSubmit={getUpdateRules(index)} - canEdit={canWriteAlerts} + canEdit={canEdit} /> ))} {Boolean(alertRules?.length) ? ( - @@ -156,6 +142,14 @@ const AlertingPageContent = () => { ); }; +const InsufficientPermissions = () => { + return ( + + You do not have the appropriate permissions to read the alert rules. To request access contact your administrator. + + ); +}; + const getStyles = (theme: GrafanaTheme2) => ({ emptyCard: css({ backgroundColor: theme.colors.background.secondary, diff --git a/src/page/CheckList/components/BulkActions.tsx b/src/page/CheckList/components/BulkActions.tsx index b2490971a..804995e32 100644 --- a/src/page/CheckList/components/BulkActions.tsx +++ b/src/page/CheckList/components/BulkActions.tsx @@ -4,8 +4,8 @@ import { Button, ButtonCascader, ConfirmModal, useStyles2 } from '@grafana/ui'; import { css } from '@emotion/css'; import { Check } from 'types'; -import { getUserPermissions } from 'data/permissions'; import { useBulkDeleteChecks, useBulkUpdateChecks } from 'data/useChecks'; +import { useCanWriteSM } from 'hooks/useDSPermission'; import { BulkActionsModal } from 'page/CheckList/components/BulkActionsModal'; interface BulkActionsProps { @@ -19,7 +19,7 @@ enum BulkAction { } export const BulkActions = ({ checks, onResolved }: BulkActionsProps) => { - const { canWriteChecks, canDeleteChecks } = getUserPermissions(); + const canEdit = useCanWriteSM(); const styles = useStyles2(getStyles); const [bulkEditAction, setBulkEditAction] = useState(null); const [showDeleteModal, setShowDeleteModal] = useState(false); @@ -62,7 +62,7 @@ export const BulkActions = ({ checks, onResolved }: BulkActionsProps) => { value: BulkAction.Remove, }, ]} - disabled={!canWriteChecks} + disabled={!canEdit} onChange={(value: string[]) => { const action = value[0] as BulkAction; setBulkEditAction(action); @@ -71,22 +71,10 @@ export const BulkActions = ({ checks, onResolved }: BulkActionsProps) => { Bulk Edit Probes )} - - @@ -95,7 +83,7 @@ export const BulkActions = ({ checks, onResolved }: BulkActionsProps) => { variant="destructive" fill="text" onClick={() => setShowDeleteModal(true)} - disabled={!canDeleteChecks} + disabled={!canEdit} > Delete diff --git a/src/page/CheckList/components/CheckItemActionButtons.tsx b/src/page/CheckList/components/CheckItemActionButtons.tsx index 99b780091..9075f78e7 100644 --- a/src/page/CheckList/components/CheckItemActionButtons.tsx +++ b/src/page/CheckList/components/CheckItemActionButtons.tsx @@ -6,8 +6,8 @@ import { css } from '@emotion/css'; import { Check } from 'types'; import { ROUTES } from 'routing/types'; import { generateRoutePath, getRoute } from 'routing/utils'; -import { getUserPermissions } from 'data/permissions'; import { useDeleteCheck } from 'data/useChecks'; +import { useCanReadMetrics, useCanWriteSM } from 'hooks/useDSPermission'; interface CheckItemActionButtonsProps { check: Check; @@ -15,7 +15,8 @@ interface CheckItemActionButtonsProps { } export const CheckItemActionButtons = ({ check, viewDashboardAsIcon }: CheckItemActionButtonsProps) => { - const { canReadChecks, canWriteChecks, canDeleteChecks } = getUserPermissions(); + const canEdit = useCanWriteSM(); + const canReadMetrics = useCanReadMetrics(); const styles = useStyles2(getStyles); const [showDeleteModal, setShowDeleteModal] = useState(false); @@ -23,7 +24,7 @@ export const CheckItemActionButtons = ({ check, viewDashboardAsIcon }: CheckItem return (
- {canReadChecks && ( + {canReadMetrics && ( <> {viewDashboardAsIcon ? ( @@ -53,7 +54,7 @@ export const CheckItemActionButtons = ({ check, viewDashboardAsIcon }: CheckItem tooltip="Delete check" name="trash-alt" onClick={() => setShowDeleteModal(true)} - disabled={!canDeleteChecks} + disabled={!canEdit} /> { - const { canWriteChecks, canWriteThresholds } = getUserPermissions(); - + const canEdit = useCanWriteSM(); const styles = useStyles2(getStyles); const [showThresholdModal, setShowThresholdModal] = useState(false); const hasChecks = checks.length > 0; @@ -96,13 +95,14 @@ export const CheckListHeader = ({ checkFilters={checkFilters} onChange={onFilterChange} /> - {canWriteThresholds && ( - + {canEdit && ( + <> + + + )} - - {canWriteChecks && }
diff --git a/src/page/ConfigPageLayout/tabs/AccessTokensTab.test.tsx b/src/page/ConfigPageLayout/tabs/AccessTokensTab.test.tsx index 7962c8924..1f629d044 100644 --- a/src/page/ConfigPageLayout/tabs/AccessTokensTab.test.tsx +++ b/src/page/ConfigPageLayout/tabs/AccessTokensTab.test.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import { runTestAsRBACAdmin, runTestAsRBACReader, runTestAsSMEditor, runTestAsSMViewer } from 'test/utils'; import { DataTestIds } from '../../../test/dataTestIds'; import { render } from '../../../test/render'; @@ -28,42 +27,14 @@ describe('AccessTokensTab', () => { expect(getByText('Access tokens', { selector: 'h2' })).toBeInTheDocument(); }); - it('should have a section on synthetic monitoring', async () => {}); + it('should have a section on synthetic monitoring', async () => { + const { getByText, queryByText } = await renderAccessTokensTab(); + expect(getByText('Synthetic Monitoring', { selector: 'h3' })).toBeInTheDocument(); + expect(queryByText('Generate access token', { selector: 'button > span' })).toBeInTheDocument(); + }); it('should have a section on private probes', async () => { const { getByText } = await renderAccessTokensTab(); expect(getByText('Private probes', { selector: 'h3' })).toBeInTheDocument(); }); - - describe('Permissions', () => { - const contactAdminMessage = `Contact your administrator to generate Access Tokens`; - - describe('When RBAC is enabled', () => { - it(`Displays a contact admin message when permissions are not met`, async () => { - runTestAsRBACReader(); - const { queryByText } = await renderAccessTokensTab(); - expect(queryByText(contactAdminMessage)).toBeInTheDocument(); - }); - - it(`Does not display a contact admin message when permissions are met`, async () => { - runTestAsRBACAdmin(); - const { queryByText } = await renderAccessTokensTab(); - expect(queryByText(contactAdminMessage)).not.toBeInTheDocument(); - }); - }); - - describe('When RBAC is disabled', () => { - it(`Displays a contact admin message when permissions are not met`, async () => { - runTestAsSMViewer(); - const { queryByText } = await renderAccessTokensTab(); - expect(queryByText(contactAdminMessage)).toBeInTheDocument(); - }); - - it(`Does not display a contact admin message when permissions are met`, async () => { - runTestAsSMEditor(); - const { queryByText } = await renderAccessTokensTab(); - expect(queryByText(contactAdminMessage)).not.toBeInTheDocument(); - }); - }); - }); }); diff --git a/src/page/ConfigPageLayout/tabs/AccessTokensTab.tsx b/src/page/ConfigPageLayout/tabs/AccessTokensTab.tsx index 8a23ed514..d6d2ed31d 100644 --- a/src/page/ConfigPageLayout/tabs/AccessTokensTab.tsx +++ b/src/page/ConfigPageLayout/tabs/AccessTokensTab.tsx @@ -2,15 +2,14 @@ import React, { useState } from 'react'; import { Alert, Button, Modal, Space, TextLink } from '@grafana/ui'; import { FaroEvent, reportError, reportEvent } from 'faro'; -import { getUserPermissions } from 'data/permissions'; +import { useCanWriteSM } from 'hooks/useDSPermission'; import { useSMDS } from 'hooks/useSMDS'; import { Clipboard } from 'components/Clipboard'; -import { ContactAdminAlert } from 'page/ContactAdminAlert'; import { ConfigContent } from '../ConfigContent'; export function AccessTokensTab() { - const { canWriteTokens } = getUserPermissions(); + const canCreateAccessToken = useCanWriteSM(); const smDS = useSMDS(); const [showModal, setShowModal] = useState(false); const [error, setError] = useState(); @@ -31,13 +30,6 @@ export function AccessTokensTab() { return ( - {!canWriteTokens && ( - - )} - You can use an SM access token to authenticate with the synthetic monitoring api. Check out the{' '} @@ -50,8 +42,8 @@ export function AccessTokensTab() { documentation to learn more about how to interact with the synthetic monitoring API.
- + {check.labels.map((label: Label, index) => ( ))} @@ -89,6 +89,7 @@ export const CheckListItemCard = ({ const getStyles = (theme: GrafanaTheme2) => ({ container: css({ backgroundColor: theme.colors.background.secondary, + border: `1px solid ${theme.colors.border.medium}`, borderRadius: '2px', }), heading: css({ diff --git a/src/page/CheckList/components/CheckListItemRow.tsx b/src/page/CheckList/components/CheckListItemRow.tsx index 137ea5dde..4ce6f1d9f 100644 --- a/src/page/CheckList/components/CheckListItemRow.tsx +++ b/src/page/CheckList/components/CheckListItemRow.tsx @@ -68,6 +68,7 @@ export const CheckListItemRow = ({ const getStyles = (theme: GrafanaTheme2) => ({ container: css({ backgroundColor: theme.colors.background.secondary, + border: `1px solid ${theme.colors.border.medium}`, borderRadius: '2px', }), disabledCard: css({ From b5aefec5c3953850cb03f39f008a05684dd5acf1 Mon Sep 17 00:00:00 2001 From: Virginia Cepeda Date: Thu, 19 Dec 2024 16:40:57 -0300 Subject: [PATCH 05/11] Revert "chore(deps): bump nanoid from 3.3.7 to 3.3.8 (#1018)" This reverts commit 77032d060323c49ed68394a6e242b0b6aa528d29. --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 2dce706a9..e0d9771bc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8709,9 +8709,9 @@ nano-css@^5.6.2: stylis "^4.3.0" nanoid@^3.3.7: - version "3.3.8" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf" - integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w== + version "3.3.7" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" + integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== natural-compare-lite@^1.4.0: version "1.4.0" From e2d7ee30c5cc5713c3b830c8e61b51a868fc8b65 Mon Sep 17 00:00:00 2001 From: Virginia Cepeda Date: Thu, 19 Dec 2024 16:41:00 -0300 Subject: [PATCH 06/11] Revert "Feat: prompt on unsaved unload (#1002)" This reverts commit 9747b2778e824059768848014c53fba616a0d95a. --- .../CheckEditor/CheckProbes/CheckProbes.tsx | 8 +- src/components/CheckEditor/ProbeOptions.tsx | 24 ++--- src/components/CheckForm/CheckForm.test.tsx | 27 ------ src/components/CheckForm/CheckForm.tsx | 6 -- .../CheckForm/FormLayout/FormLayout.test.tsx | 88 ++--------------- .../CheckForm/FormLayout/FormLayout.tsx | 13 +-- .../ConfirmLeavingPage.test.tsx | 96 ------------------- .../ConfirmLeavingPage/ConfirmLeavingPage.tsx | 82 ---------------- .../ConfirmUnsavedModal.test.tsx | 54 ----------- .../ConfirmUnsavedModal.tsx | 26 ----- src/components/ConfirmLeavingPage/index.ts | 1 - src/hooks/useConfirmBeforeUnload.test.ts | 24 ----- src/hooks/useConfirmBeforeUnload.ts | 24 ----- .../HTTPCheck/Submit.test.tsx | 14 +-- .../TCPCheck/Submit.test.tsx | 14 +-- .../EditCheck/__tests__/EditCheck.test.tsx | 4 +- src/page/NewCheck/NewCheck.test.tsx | 71 -------------- src/page/NewCheck/NewCheck.tsx | 3 +- .../DNSCheck/5-execution.ui.test.tsx | 2 - ...eck.journey.test.tsx => NewCheck.test.tsx} | 13 ++- src/page/NotFound/index.ts | 2 - src/page/__testHelpers__/checkForm.tsx | 2 +- src/test/dataTestIds.ts | 2 - 23 files changed, 49 insertions(+), 551 deletions(-) delete mode 100644 src/components/CheckForm/CheckForm.test.tsx delete mode 100644 src/components/ConfirmLeavingPage/ConfirmLeavingPage.test.tsx delete mode 100644 src/components/ConfirmLeavingPage/ConfirmLeavingPage.tsx delete mode 100644 src/components/ConfirmLeavingPage/ConfirmUnsavedModal.test.tsx delete mode 100644 src/components/ConfirmLeavingPage/ConfirmUnsavedModal.tsx delete mode 100644 src/components/ConfirmLeavingPage/index.ts delete mode 100644 src/hooks/useConfirmBeforeUnload.test.ts delete mode 100644 src/hooks/useConfirmBeforeUnload.ts delete mode 100644 src/page/NewCheck/NewCheck.test.tsx rename src/page/NewCheck/__tests__/{NewCheck.journey.test.tsx => NewCheck.test.tsx} (92%) delete mode 100644 src/page/NotFound/index.ts diff --git a/src/components/CheckEditor/CheckProbes/CheckProbes.tsx b/src/components/CheckEditor/CheckProbes/CheckProbes.tsx index e469e8659..b4072639d 100644 --- a/src/components/CheckEditor/CheckProbes/CheckProbes.tsx +++ b/src/components/CheckEditor/CheckProbes/CheckProbes.tsx @@ -1,4 +1,4 @@ -import React, { useMemo, useState } from 'react'; +import React, { forwardRef, useMemo, useState } from 'react'; import { Field, Stack } from '@grafana/ui'; import { Probe } from 'types'; @@ -16,7 +16,7 @@ interface CheckProbesProps { invalid?: boolean; error?: string; } -export function CheckProbes({ probes, availableProbes, onChange, error }: CheckProbesProps) { +export const CheckProbes = forwardRef(({ probes, availableProbes, onChange, error }: CheckProbesProps) => { const [filteredProbes, setFilteredProbes] = useState(availableProbes); const publicProbes = useMemo(() => filteredProbes.filter((probe) => probe.public), [filteredProbes]); @@ -73,4 +73,6 @@ export function CheckProbes({ probes, availableProbes, onChange, error }: CheckP {showPrivateProbesDiscovery && } ); -} +}); + +CheckProbes.displayName = 'CheckProbes'; diff --git a/src/components/CheckEditor/ProbeOptions.tsx b/src/components/CheckEditor/ProbeOptions.tsx index 3639712b2..fe6c73ec4 100644 --- a/src/components/CheckEditor/ProbeOptions.tsx +++ b/src/components/CheckEditor/ProbeOptions.tsx @@ -26,20 +26,16 @@ export const ProbeOptions = ({ checkType, disabled }: ProbeOptionsProps) => { { - const { ref, ...fieldProps } = field; // ref is unused, this is to silence warnings - - return ( - - ); - }} + render={({ field }) => ( + + )} /> ); - await screen.findByTestId(DataTestIds.CHECK_FORM_SUBMIT_BUTTON); // Wait for the form to be rendered - - return result; -} - -describe(``, () => { - it(`should render without props`, async () => { - await renderCheckForm(); - expect(screen.getByTestId(DataTestIds.CHECK_FORM_SUBMIT_BUTTON)).not.toBeEnabled(); - }); -}); diff --git a/src/components/CheckForm/CheckForm.tsx b/src/components/CheckForm/CheckForm.tsx index 1e063c2d2..96e16914d 100644 --- a/src/components/CheckForm/CheckForm.tsx +++ b/src/components/CheckForm/CheckForm.tsx @@ -32,7 +32,6 @@ import { LayoutSection } from 'components/CheckForm/FormLayouts/Layout.types'; import { CheckFormAlert } from 'components/CheckFormAlert'; import { CheckTestResultsModal } from 'components/CheckTestResultsModal'; import { CheckUsage } from 'components/CheckUsage'; -import { ConfirmLeavingPage } from 'components/ConfirmLeavingPage'; import { fallbackCheckMap } from 'components/constants'; import { LabelField } from 'components/LabelField'; import { OverLimitAlert } from 'components/OverLimitAlert'; @@ -157,9 +156,6 @@ export const CheckForm = ({ check, disabled }: CheckFormProps) => { ); - const { isDirty, isSubmitSuccessful } = formMethods.formState; - // since we navigate on submit, we need this to not trigger the confirmation modal - const hasUnsavedChanges = isDirty && !isSubmitSuccessful; const navModel = useMemo(() => { return isExistingCheck ? createNavModel( @@ -190,7 +186,6 @@ export const CheckForm = ({ check, disabled }: CheckFormProps) => { onValid={handleValid} onInvalid={handleInvalid} schema={schema} - hasUnsavedChanges={hasUnsavedChanges} > {!isExistingCheck && } @@ -227,7 +222,6 @@ export const CheckForm = ({ check, disabled }: CheckFormProps) => { - ); }; diff --git a/src/components/CheckForm/FormLayout/FormLayout.test.tsx b/src/components/CheckForm/FormLayout/FormLayout.test.tsx index 5d41c314b..7ed5ed9c1 100644 --- a/src/components/CheckForm/FormLayout/FormLayout.test.tsx +++ b/src/components/CheckForm/FormLayout/FormLayout.test.tsx @@ -55,7 +55,7 @@ describe(`FormLayout`, () => { ); - const submitButton = await screen.findByTestId(DataTestIds.CHECK_FORM_SUBMIT_BUTTON); + const submitButton = await screen.findByText(`Submit`); await user.click(submitButton); const errorIcon = await container.querySelector(`svg[name='exclamation-triangle']`); expect(errorIcon).toBeInTheDocument(); @@ -126,7 +126,7 @@ describe(`FormLayout`, () => { ); - const submitButton = await screen.findByTestId(DataTestIds.CHECK_FORM_SUBMIT_BUTTON); + const submitButton = await screen.findByRole(`button`, { name: `Submit` }); expect(submitButton).toBeDisabled(); }); @@ -202,7 +202,7 @@ describe(`FormLayout`, () => { expect(within(actionsBar).getAllByRole(`button`).length).toBe(2); expect(within(actionsBar).getByText(secondSectionLabel)).toBeInTheDocument(); expect(within(actionsBar).queryByText(firstSectionLabel)).not.toBeInTheDocument(); - expect(within(actionsBar).getByTestId(DataTestIds.CHECK_FORM_SUBMIT_BUTTON)).toBeInTheDocument(); + expect(within(actionsBar).getByText(`Submit`)).toBeInTheDocument(); // when on step 2 await user.click(within(actionsBar).getByText(secondSectionLabel)); @@ -210,7 +210,7 @@ describe(`FormLayout`, () => { expect(within(actionsBar).getByText(firstSectionLabel)).toBeInTheDocument(); expect(within(actionsBar).queryByText(secondSectionLabel)).not.toBeInTheDocument(); expect(within(actionsBar).getByText(thirdSectionLabel)).toBeInTheDocument(); - expect(within(actionsBar).getByTestId(DataTestIds.CHECK_FORM_SUBMIT_BUTTON)).toBeInTheDocument(); + expect(within(actionsBar).getByText(`Submit`)).toBeInTheDocument(); // when on step 3 await user.click(within(actionsBar).getByText(thirdSectionLabel)); @@ -218,7 +218,7 @@ describe(`FormLayout`, () => { expect(within(actionsBar).queryByText(firstSectionLabel)).not.toBeInTheDocument(); expect(within(actionsBar).getByText(secondSectionLabel)).toBeInTheDocument(); expect(within(actionsBar).queryByText(thirdSectionLabel)).not.toBeInTheDocument(); - expect(within(actionsBar).getByTestId(DataTestIds.CHECK_FORM_SUBMIT_BUTTON)).toBeInTheDocument(); + expect(within(actionsBar).getByText(`Submit`)).toBeInTheDocument(); }); it(`renders custom action buttons correctly`, async () => { @@ -281,82 +281,10 @@ describe(`FormLayout`, () => { const lastSection = await screen.findByText(thirdSectionLabel); await user.click(lastSection); expect(screen.getByText(thirdSectionContent)).toBeInTheDocument(); - await user.click(screen.getByTestId(DataTestIds.CHECK_FORM_SUBMIT_BUTTON)); + await user.click(screen.getByText(`Submit`)); const firstSection = await screen.findByText(secondSectionContent); expect(firstSection).toBeInTheDocument(); }); - - it('submit button text should be Save', async () => { - render( - - - - - - ); - - const submitButton = await screen.findByTestId(DataTestIds.CHECK_FORM_SUBMIT_BUTTON); - expect(submitButton).toHaveTextContent('Save'); - }); - - describe('hasUnsavedChanges prop', () => { - it('should disable submit button when false', async () => { - const { user } = render( - - - - - - ); - - const submitButton = await screen.findByTestId(DataTestIds.CHECK_FORM_SUBMIT_BUTTON); - expect(submitButton).toBeDisabled(); - - const jobInput = await screen.findByLabelText('Job'); - jobInput.focus(); - await user.type(jobInput, 'job'); - expect(jobInput).toBeEnabled(); - }); - - it('should enable submit button when undefined', async () => { - render( - - - - - - ); - - const submitButton = await screen.findByTestId(DataTestIds.CHECK_FORM_SUBMIT_BUTTON); - expect(submitButton).toBeEnabled(); - }); - - it('should enable submit button when true', async () => { - render( - - - - - - ); - - const submitButton = await screen.findByTestId(DataTestIds.CHECK_FORM_SUBMIT_BUTTON); - expect(submitButton).toBeEnabled(); - }); - - it('should not enable submit button when form is disabled', async () => { - render( - - - - - - ); - - const submitButton = await screen.findByTestId(DataTestIds.CHECK_FORM_SUBMIT_BUTTON); - expect(submitButton).toBeDisabled(); - }); - }); }); type TestValues = { @@ -373,8 +301,7 @@ const TestForm = ({ actions, children, disabled, - hasUnsavedChanges, -}: Pick, 'actions' | 'children' | 'disabled' | 'hasUnsavedChanges'>) => { +}: Pick, 'actions' | 'children' | 'disabled'>) => { const formMethods = useForm({ defaultValues: { job: ``, @@ -391,7 +318,6 @@ const TestForm = ({ onSubmit={formMethods.handleSubmit} onValid={(v) => v} schema={schema} - hasUnsavedChanges={hasUnsavedChanges} > {children} diff --git a/src/components/CheckForm/FormLayout/FormLayout.tsx b/src/components/CheckForm/FormLayout/FormLayout.tsx index 05be96783..1a4195e34 100644 --- a/src/components/CheckForm/FormLayout/FormLayout.tsx +++ b/src/components/CheckForm/FormLayout/FormLayout.tsx @@ -28,7 +28,6 @@ export type FormLayoutProps = { onValid: SubmitHandler; onInvalid?: (errs: FieldErrors) => void; schema: ZodType; - hasUnsavedChanges?: boolean; }; export const FORM_MAX_WIDTH = `860px`; @@ -42,7 +41,6 @@ export const FormLayout = ({ onValid, onInvalid, schema, - hasUnsavedChanges = true, // default to true to prevent accidentally disabling the submit button }: FormLayoutProps) => { const styles = useStyles2(getStyles); const { activeSection, setActiveSection, goToSection, setVisited, visitedSections } = useFormLayout(disabled); @@ -108,8 +106,6 @@ export const FormLayout = ({ const actionButtons = actions?.find((action) => action.index === activeSection)?.element; - const disableSubmit = !hasUnsavedChanges || disabled; - return (
@@ -147,13 +143,8 @@ export const FormLayout = ({ )} -
diff --git a/src/components/ConfirmLeavingPage/ConfirmLeavingPage.test.tsx b/src/components/ConfirmLeavingPage/ConfirmLeavingPage.test.tsx deleted file mode 100644 index 19e6a16dd..000000000 --- a/src/components/ConfirmLeavingPage/ConfirmLeavingPage.test.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import React, { PropsWithChildren } from 'react'; -import { Router } from 'react-router-dom'; -import { CompatRouter, Route, Routes } from 'react-router-dom-v5-compat'; -import { locationService } from '@grafana/runtime'; -import { TextLink } from '@grafana/ui'; -import { fireEvent, render, screen } from '@testing-library/react'; -import userEventLib from '@testing-library/user-event'; - -import { DataTestIds } from '../../test/dataTestIds'; -import { ConfirmLeavingPage } from './ConfirmLeavingPage'; - -const TEST_IDS = { - INITIAL_PAGE: 'ConfirmLeavingPage.initial-page', - LEAVE_PAGE_LINK: 'ConfirmLeavingPage.leave-page-link', - OTHER_PAGE: 'ConfirmLeavingPage.other-route', -} as const; - -beforeAll(() => { - // History needs to be reset manually between tests as it uses Grafana's global locationService - locationService.replace('/'); -}); - -afterEach(() => { - // History needs to be reset manually between tests as it uses Grafana's global locationService - locationService.replace('/'); -}); - -function Wrapper({ children }: PropsWithChildren<{}>) { - const history = locationService.getHistory(); - // History will not automatically be reset between tests - - return ( - - - - {children}
} /> - } /> - - - - ); -} - -describe('ConfirmLeavingPage', () => { - it.each([false, true, undefined])('should not render anything on mount (enabled: %s)', async (enabled) => { - // @ts-expect-error Intentionally testing with `undefined` - render(, { wrapper: Wrapper }); - const container = screen.queryByTestId(TEST_IDS.INITIAL_PAGE); - expect(container).toBeEmptyDOMElement(); - }); - - describe('router navigation', () => { - it.each([ - ['Stay on page', TEST_IDS.INITIAL_PAGE], - ['Leave page', TEST_IDS.OTHER_PAGE], - ])('should render a modal when navigating away (%s)', async (buttonText, expectedTestId) => { - render( - <> - - Leave page - - - , - { wrapper: Wrapper } - ); - - expect(await screen.findByTestId(TEST_IDS.INITIAL_PAGE)).toBeInTheDocument(); - await new Promise((resolve) => setTimeout(resolve, 0)); - const user = userEventLib.setup(); - const link = screen.getByTestId(TEST_IDS.LEAVE_PAGE_LINK); - await user.click(link); - expect(await screen.findByTestId(DataTestIds.CONFIRM_UNSAVED_MODAL_HEADING)).toBeInTheDocument(); - await user.click(screen.getByText(buttonText, { selector: 'button > span' })); - expect(await screen.findByTestId(expectedTestId)).toBeInTheDocument(); - }); - }); - - describe('onbeforeunload', () => { - it('should trigger confirm on beforeunload', async () => { - render( - <> - - Leave page - - - , - { wrapper: Wrapper } - ); - - expect(await screen.findByTestId(TEST_IDS.INITIAL_PAGE)).toBeInTheDocument(); - const event = new Event('beforeunload', { cancelable: true }); - fireEvent(window, event); - expect(event.defaultPrevented).toBe(true); - }); - }); -}); diff --git a/src/components/ConfirmLeavingPage/ConfirmLeavingPage.tsx b/src/components/ConfirmLeavingPage/ConfirmLeavingPage.tsx deleted file mode 100644 index 884dd389c..000000000 --- a/src/components/ConfirmLeavingPage/ConfirmLeavingPage.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import React, { useCallback, useEffect, useState } from 'react'; -import { useLocation, useNavigate } from 'react-router-dom-v5-compat'; -import { locationService } from '@grafana/runtime'; -import { Location, TransitionPromptHook } from 'history'; - -import { useConfirmBeforeUnload } from 'hooks/useConfirmBeforeUnload'; - -import { ConfirmUnsavedModal } from './ConfirmUnsavedModal'; - -interface ConfirmLeavingPageProps { - enabled: boolean; -} - -/** - * When enabled is `true`, will block `react-router-dom` navigation with confirm modal. - * Native navigations are handled with native `confirm` - * - * @example - * - * - * @see {useConfirmBeforeUnload} - * @param {boolean} enabled Whether or not to actively block transitions - * @constructor - */ -export function ConfirmLeavingPage({ enabled }: ConfirmLeavingPageProps) { - const [showModal, setShowModal] = useState(false); - const [blockedLocation, setBlockedLocation] = useState(null); - const [changesDiscarded, setChangesDiscarded] = useState(false); - const navigate = useNavigate(); - const history = locationService.getHistory(); - useConfirmBeforeUnload(enabled); - - const location = useLocation(); - - const blockHandler: TransitionPromptHook = useCallback( - (nextLocation: Location) => { - const path = location.pathname; - const nextPath = nextLocation.pathname; - - // Check all the reasons to allow navigation - if (!enabled || path === nextPath || changesDiscarded) { - return; - } - - setBlockedLocation(nextLocation); - setShowModal(true); - return false; - }, - [changesDiscarded, enabled, location.pathname] - ); - - useEffect(() => { - const unblock = history.block(blockHandler); - - return () => { - unblock(); - }; - }, [blockHandler, blockedLocation, history]); - - useEffect(() => { - if (changesDiscarded && blockedLocation) { - navigate(blockedLocation.pathname); - } - }, [blockedLocation, changesDiscarded, navigate]); - - const handleLeavePage = useCallback(() => { - setShowModal(false); - setChangesDiscarded(true); - }, []); - - const handleStayOnPage = useCallback(() => { - setShowModal(false); - setBlockedLocation(null); - setChangesDiscarded(false); - }, []); - - if (showModal) { - return ; - } - - return null; -} diff --git a/src/components/ConfirmLeavingPage/ConfirmUnsavedModal.test.tsx b/src/components/ConfirmLeavingPage/ConfirmUnsavedModal.test.tsx deleted file mode 100644 index 1e420cc52..000000000 --- a/src/components/ConfirmLeavingPage/ConfirmUnsavedModal.test.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import React from 'react'; -import { screen } from '@testing-library/react'; -import { DataTestIds } from 'test/dataTestIds'; -import { render } from 'test/render'; - -import { ConfirmUnsavedModal } from './ConfirmUnsavedModal'; - -describe('', () => { - it('should show when rendered', async () => { - render(); - - expect(await screen.findByTestId(DataTestIds.CONFIRM_UNSAVED_MODAL_HEADING)).toBeInTheDocument(); - }); - - it('should call onLeavePage when leave page button clicked', async () => { - const onLeavePage = jest.fn(); - render(); - - await screen.findByText('Leave page').then((button) => button.click()); - - expect(onLeavePage).toHaveBeenCalled(); - }); - - it('should call onStayOnPage when stay on page button clicked', async () => { - const onStayOnPage = jest.fn(); - render(); - - await screen.findByText('Stay on page').then((button) => button.click()); - - expect(onStayOnPage).toHaveBeenCalled(); - }); - - it('should call onStayOnPage when modal is dismissed (button)', async () => { - const onStayOnPage = jest.fn(); - const { user } = render(); - - await screen.findByTestId('confirm-unsaved-modal-heading'); - const closeButton = screen.getByRole('button', { name: 'Close' }); - - await user.click(closeButton); - - expect(onStayOnPage).toHaveBeenCalled(); - }); - - it('should call onStayOnPage when modal is dismissed (keyboard)', async () => { - const onStayOnPage = jest.fn(); - const { user } = render(); - - await screen.findByTestId('confirm-unsaved-modal-heading'); - await user.keyboard('{Esc}'); - - expect(onStayOnPage).toHaveBeenCalled(); - }); -}); diff --git a/src/components/ConfirmLeavingPage/ConfirmUnsavedModal.tsx b/src/components/ConfirmLeavingPage/ConfirmUnsavedModal.tsx deleted file mode 100644 index 1c9a1d2f1..000000000 --- a/src/components/ConfirmLeavingPage/ConfirmUnsavedModal.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import React from 'react'; -import { Button, Modal, Text } from '@grafana/ui'; -import { DataTestIds } from 'test/dataTestIds'; - -interface ConfirmUnsavedModalProps { - onLeavePage: () => void; - onStayOnPage: () => void; -} - -export function ConfirmUnsavedModal({ onLeavePage, onStayOnPage }: ConfirmUnsavedModalProps) { - return ( - - - You have unsaved changes. Are you sure you want to leave this page? - - - - - - - ); -} diff --git a/src/components/ConfirmLeavingPage/index.ts b/src/components/ConfirmLeavingPage/index.ts deleted file mode 100644 index 85a129c38..000000000 --- a/src/components/ConfirmLeavingPage/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './ConfirmLeavingPage'; diff --git a/src/hooks/useConfirmBeforeUnload.test.ts b/src/hooks/useConfirmBeforeUnload.test.ts deleted file mode 100644 index e98d0f87e..000000000 --- a/src/hooks/useConfirmBeforeUnload.test.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { useBeforeUnload } from 'react-router-dom-v5-compat'; -import { renderHook } from '@testing-library/react'; - -import { useConfirmBeforeUnload } from './useConfirmBeforeUnload'; - -jest.mock('react-router-dom-v5-compat', () => { - const originalModule = jest.requireActual('react-router-dom-v5-compat'); - return { - ...originalModule, - useBeforeUnload: jest.fn(), - }; -}); - -describe('useConfirmBeforeUnload', () => { - it('not throw when used without param', () => { - // @ts-expect-error - Testing without param - expect(() => renderHook(() => useConfirmBeforeUnload())).not.toThrow(); - }); - - it.each([true, false])('should call useBeforeUnload with handler (%s)', () => { - renderHook(() => useConfirmBeforeUnload(true)); - expect(useBeforeUnload).toHaveBeenCalled(); - }); -}); diff --git a/src/hooks/useConfirmBeforeUnload.ts b/src/hooks/useConfirmBeforeUnload.ts deleted file mode 100644 index ed8307ee2..000000000 --- a/src/hooks/useConfirmBeforeUnload.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { useCallback } from 'react'; -import { useBeforeUnload } from 'react-router-dom-v5-compat'; - -/** - * Hook that blocks the user from leaving/reloading the page when the confirm parameter is `true`. - * - * @note This does not hinder location change within app router. - * @param {boolean} confirm - * @example - * useBeforeUnload(formState.isDirty); - */ -export function useConfirmBeforeUnload(confirm: boolean) { - const handler = useCallback( - (event: BeforeUnloadEvent) => { - if (confirm) { - event.preventDefault(); - event.returnValue = ''; // legacy support - } - }, - [confirm] - ); - - useBeforeUnload(handler); -} diff --git a/src/page/EditCheck/__tests__/ApiEndPointChecks/HTTPCheck/Submit.test.tsx b/src/page/EditCheck/__tests__/ApiEndPointChecks/HTTPCheck/Submit.test.tsx index 12f6d3eed..9029d3cf3 100644 --- a/src/page/EditCheck/__tests__/ApiEndPointChecks/HTTPCheck/Submit.test.tsx +++ b/src/page/EditCheck/__tests__/ApiEndPointChecks/HTTPCheck/Submit.test.tsx @@ -1,12 +1,9 @@ -import { screen } from '@testing-library/react'; import { PRIVATE_PROBE } from 'test/fixtures/probes'; import { apiRoute } from 'test/handlers'; import { server } from 'test/server'; import { HTTPCheck, HttpMethod, IpVersion } from 'types'; -import { renderEditForm } from 'page/__testHelpers__/checkForm'; - -import { DataTestIds } from '../../../../../test/dataTestIds'; +import { renderEditForm, submitForm } from 'page/__testHelpers__/checkForm'; const MIN_HTTP_CHECK: HTTPCheck = { id: 1, @@ -32,7 +29,7 @@ const MIN_HTTP_CHECK: HTTPCheck = { alertSensitivity: 'none', }; -it(`HTTPCheck -- can not submit an existing check without editing`, async () => { +it(`HTTPCheck -- can successfully submit an existing check with no editing`, async () => { server.use( apiRoute(`listChecks`, { result: () => { @@ -43,6 +40,9 @@ it(`HTTPCheck -- can not submit an existing check without editing`, async () => }) ); - await renderEditForm(MIN_HTTP_CHECK.id); - expect(await screen.findByTestId(DataTestIds.CHECK_FORM_SUBMIT_BUTTON)).not.toBeEnabled(); + const { read, user } = await renderEditForm(MIN_HTTP_CHECK.id); + await submitForm(user); + + const { body } = await read(); + expect(body).toBeTruthy(); }); diff --git a/src/page/EditCheck/__tests__/ApiEndPointChecks/TCPCheck/Submit.test.tsx b/src/page/EditCheck/__tests__/ApiEndPointChecks/TCPCheck/Submit.test.tsx index c0b402890..d0def16e5 100644 --- a/src/page/EditCheck/__tests__/ApiEndPointChecks/TCPCheck/Submit.test.tsx +++ b/src/page/EditCheck/__tests__/ApiEndPointChecks/TCPCheck/Submit.test.tsx @@ -1,12 +1,9 @@ -import { screen } from '@testing-library/react'; import { PRIVATE_PROBE } from 'test/fixtures/probes'; import { apiRoute } from 'test/handlers'; import { server } from 'test/server'; import { IpVersion, TCPCheck } from 'types'; -import { renderEditForm } from 'page/__testHelpers__/checkForm'; - -import { DataTestIds } from '../../../../../test/dataTestIds'; +import { renderEditForm, submitForm } from 'page/__testHelpers__/checkForm'; const MIN_TCP_CHECK: TCPCheck = { id: 1, @@ -28,7 +25,7 @@ const MIN_TCP_CHECK: TCPCheck = { alertSensitivity: 'none', }; -it(`TCPCheck -- can not submit an existing check without editing`, async () => { +it(`TCPCheck -- can successfully submit an existing check with no editing`, async () => { server.use( apiRoute(`listChecks`, { result: () => { @@ -39,7 +36,10 @@ it(`TCPCheck -- can not submit an existing check without editing`, async () => { }) ); - await renderEditForm(MIN_TCP_CHECK.id); + const { read, user } = await renderEditForm(MIN_TCP_CHECK.id); + + await submitForm(user); - expect(await screen.findByTestId(DataTestIds.CHECK_FORM_SUBMIT_BUTTON)).not.toBeEnabled(); + const { body } = await read(); + expect(body).toBeTruthy(); }); diff --git a/src/page/EditCheck/__tests__/EditCheck.test.tsx b/src/page/EditCheck/__tests__/EditCheck.test.tsx index dc6585363..ad5bdfe07 100644 --- a/src/page/EditCheck/__tests__/EditCheck.test.tsx +++ b/src/page/EditCheck/__tests__/EditCheck.test.tsx @@ -51,7 +51,7 @@ describe(``, () => { it(`disables the form when the user is a viewer`, async () => { runTestAsViewer(); - const { container } = await renderEditForm(BASIC_HTTP_CHECK.id); - expect(container.querySelector('#check-editor-job-input')).toBeDisabled(); + await renderEditForm(BASIC_HTTP_CHECK.id); + expect(screen.getByRole(`button`, { name: `Submit` })).toBeDisabled(); }); }); diff --git a/src/page/NewCheck/NewCheck.test.tsx b/src/page/NewCheck/NewCheck.test.tsx deleted file mode 100644 index feb1208bb..000000000 --- a/src/page/NewCheck/NewCheck.test.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import React, { ReactNode } from 'react'; -import { screen, waitFor } from '@testing-library/react'; -import { render } from 'test/render'; - -import { CheckTypeGroup } from '../../types'; -import { CheckForm } from 'components/CheckForm/CheckForm'; - -import { PluginPageNotFound } from '../NotFound'; -import { NewCheck } from './NewCheck'; - -enum NewCheckTestIds { - Ready = 'NewCheck.Ready', - CheckForm = 'NewCheck.CheckForm', - PluginPageNotFound = 'NewCheck.PluginPageNotFound', -} - -function ReadyComponent({ children }: { children: ReactNode }) { - return
{children}
; -} - -jest.mock('components/CheckForm/CheckForm', () => ({ - CheckForm: jest.fn().mockImplementation(() => ( - -
- - )), -})); - -jest.mock('page/NotFound', () => ({ - PluginPageNotFound: jest.fn().mockImplementation(() => ( - -
- - )), -})); - -async function renderNewCheck(options?: any) { - const result = render(, options); - await waitFor(() => expect(screen.getByTestId(NewCheckTestIds.Ready)).toBeInTheDocument()); - - return result; -} - -// The acts as a safe-guard for the check form, ensuring that the check type group is valid before rendering -describe('', () => { - it(`should render without props`, async () => { - const { container } = await renderNewCheck(); - expect(container).toBeInTheDocument(); - }); - - it.each(Object.values(CheckTypeGroup))( - 'should render for valid check type groups (%s)', - async (checkTypeGroup) => { - await renderNewCheck({ route: ':checkTypeGroup', path: checkTypeGroup }); - expect(screen.getByTestId(NewCheckTestIds.CheckForm)).toBeInTheDocument(); - expect(CheckForm).toHaveBeenCalledTimes(1); - } - ); - - it('should render not found page for invalid check type group', async () => { - await renderNewCheck({ route: ':checkTypeGroup', path: 'this-is-not-a-check-type-group' }); - expect(screen.getByTestId(NewCheckTestIds.PluginPageNotFound)).toBeInTheDocument(); - expect(PluginPageNotFound).toHaveBeenCalledTimes(1); - }); - - it('should render not found page when :checkTypeGroup param is missing', async () => { - await renderNewCheck(); - expect(screen.getByTestId(NewCheckTestIds.PluginPageNotFound)).toBeInTheDocument(); - expect(PluginPageNotFound).toHaveBeenCalledTimes(1); - }); -}); diff --git a/src/page/NewCheck/NewCheck.tsx b/src/page/NewCheck/NewCheck.tsx index 6f98991fb..315d24d0e 100644 --- a/src/page/NewCheck/NewCheck.tsx +++ b/src/page/NewCheck/NewCheck.tsx @@ -7,7 +7,8 @@ import { ROUTES } from 'routing/types'; import { getRoute } from 'routing/utils'; import { CHECK_TYPE_GROUP_OPTIONS } from 'hooks/useCheckTypeGroupOptions'; import { CheckForm } from 'components/CheckForm/CheckForm'; -import { PluginPageNotFound } from 'page/NotFound'; + +import { PluginPageNotFound } from '../NotFound/NotFound'; export const NewCheck = () => { const { checkTypeGroup } = useParams(); diff --git a/src/page/NewCheck/__tests__/ApiEndPointChecks/DNSCheck/5-execution.ui.test.tsx b/src/page/NewCheck/__tests__/ApiEndPointChecks/DNSCheck/5-execution.ui.test.tsx index 5e87139fe..8082c8ae9 100644 --- a/src/page/NewCheck/__tests__/ApiEndPointChecks/DNSCheck/5-execution.ui.test.tsx +++ b/src/page/NewCheck/__tests__/ApiEndPointChecks/DNSCheck/5-execution.ui.test.tsx @@ -11,8 +11,6 @@ describe(`DNSCheck - Section 5 (Execution) UI`, () => { const { user } = await renderNewForm(checkType); await goToSection(user, 3); - const addLabelButton = screen.getByText('Add label', { selector: 'button > span' }); - await user.click(addLabelButton); await submitForm(user); expect(screen.getByText(`Job name is required`)).toBeInTheDocument(); }); diff --git a/src/page/NewCheck/__tests__/NewCheck.journey.test.tsx b/src/page/NewCheck/__tests__/NewCheck.test.tsx similarity index 92% rename from src/page/NewCheck/__tests__/NewCheck.journey.test.tsx rename to src/page/NewCheck/__tests__/NewCheck.test.tsx index 9c75d0e89..6bf267fcc 100644 --- a/src/page/NewCheck/__tests__/NewCheck.journey.test.tsx +++ b/src/page/NewCheck/__tests__/NewCheck.test.tsx @@ -1,5 +1,4 @@ import { screen, waitFor } from '@testing-library/react'; -import { DataTestIds } from 'test/dataTestIds'; import { apiRoute } from 'test/handlers'; import { server } from 'test/server'; import { runTestAsHGFreeUserOverLimit, runTestWithoutLogsAccess } from 'test/utils'; @@ -8,7 +7,7 @@ import { CheckType } from 'types'; import { fillMandatoryFields } from 'page/__testHelpers__/apiEndPoint'; import { goToSection, renderNewForm, submitForm } from 'page/__testHelpers__/checkForm'; -describe(` journey`, () => { +describe(``, () => { it(`should show an error message when it fails to save a check`, async () => { const { user } = await renderNewForm(CheckType.HTTP); server.use( @@ -67,8 +66,8 @@ describe(` journey`, () => { }) ); - const { container } = await renderNewForm(CheckType.HTTP); - expect(container.querySelector('#check-editor-job-input')).toBeDisabled(); + await renderNewForm(CheckType.HTTP); + expect(screen.getByRole(`button`, { name: /Submit/ })).toBeDisabled(); }); it(`should NOT disable the form when the check limit can't be fetched`, async () => { @@ -82,8 +81,8 @@ describe(` journey`, () => { }) ); - const { container } = await renderNewForm(CheckType.HTTP); - expect(container.querySelector('#check-editor-job-input')).not.toBeDisabled(); + await renderNewForm(CheckType.HTTP); + expect(screen.getByRole(`button`, { name: /Submit/ })).toBeEnabled(); }); it(`should show the mothly execution limit warning when the limit is reached for HG free tier customers`, async () => { @@ -97,7 +96,7 @@ describe(` journey`, () => { runTestAsHGFreeUserOverLimit(); await renderNewForm(CheckType.HTTP); - expect(screen.getByTestId(DataTestIds.CHECK_FORM_SUBMIT_BUTTON)).toBeDisabled(); + expect(screen.getByRole(`button`, { name: /Submit/ })).toBeDisabled(); }); it(`should focus the probes filter component when appropriate`, async () => { diff --git a/src/page/NotFound/index.ts b/src/page/NotFound/index.ts deleted file mode 100644 index 7f8d6b520..000000000 --- a/src/page/NotFound/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './NotFound'; -export * from './CheckNotFound'; diff --git a/src/page/__testHelpers__/checkForm.tsx b/src/page/__testHelpers__/checkForm.tsx index a7cfce7ed..9ee8f2997 100644 --- a/src/page/__testHelpers__/checkForm.tsx +++ b/src/page/__testHelpers__/checkForm.tsx @@ -89,7 +89,7 @@ export async function goToSection(user: UserEvent, sectionIndex: 1 | 2 | 3 | 4 | } export async function submitForm(user: UserEvent) { - const saveButton = await screen.findByTestId(DataTestIds.CHECK_FORM_SUBMIT_BUTTON); + const saveButton = await screen.findByText('Submit'); await user.click(saveButton); } diff --git a/src/test/dataTestIds.ts b/src/test/dataTestIds.ts index 3fe131532..129560274 100644 --- a/src/test/dataTestIds.ts +++ b/src/test/dataTestIds.ts @@ -22,6 +22,4 @@ export enum DataTestIds { CONFIG_CONTENT = 'config-content', CONFIG_CONTENT_LOADING = 'config-content-loading', PREFORMATTED = 'preformatted', - CHECK_FORM_SUBMIT_BUTTON = 'check-form-submit-button', - CONFIRM_UNSAVED_MODAL_HEADING = 'confirm-unsaved-modal-heading', } From 2df6b869ffebee745c875de7918a0a79aa972f48 Mon Sep 17 00:00:00 2001 From: Virginia Cepeda Date: Thu, 19 Dec 2024 16:41:02 -0300 Subject: [PATCH 07/11] Revert "fix: add synthetic-monitoring-dev as owners of release files (#1010)" This reverts commit d703e426e1e8a4c67689dd9794c4fd1f500fcf09. --- CODEOWNERS | 9 --------- 1 file changed, 9 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 7c3447890..36906c461 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -2,12 +2,3 @@ # https://git-scm.com/docs/gitignore#_pattern_format * @grafana/synthetic-monitoring-fe - -# These files are updated by release-please and we need any member of the -# larger team to be able to approve them. -# -# The docs seem to suggest that the last matching pattern is the one that is -# used, so we need to keep the * pattern above this one. -/CHANGELOG.md @grafana/synthetic-monitoring-fe @grafana/synthetic-monitoring-dev -/package.json @grafana/synthetic-monitoring-fe @grafana/synthetic-monitoring-dev -/.github/release-please/release-please-config.json @grafana/synthetic-monitoring-fe @grafana/synthetic-monitoring-dev From a033bd733c8e8a164200da6485bc69b5758c80ff Mon Sep 17 00:00:00 2001 From: Virginia Cepeda Date: Thu, 19 Dec 2024 16:41:05 -0300 Subject: [PATCH 08/11] Revert "Chore/autumn clean (#1005)" This reverts commit 279272d07215fdf3a6083d4607d59234848775fa. --- .release-it.js | 21 + CHANGELOG_DEPRECATED.md | 730 ++++++++++++++++++ __mocks__/@grafana/faro-web-sdk.ts | 11 + __mocks__/@grafana/ui.tsx | 42 + __mocks__/components/SimpleMap/index.tsx | 5 + __mocks__/grafana/app/core/app_events.ts | 5 + cspell.config.json | 5 + dummy.scss | 1 + jest.config.js | 9 +- package.json | 1 + src/components/Autosizer.tsx | 43 ++ src/components/__mocks__/Autosizer.tsx | 14 + .../unsupported_file.js => fileMock.js} | 0 src/test/jest-setup.tsx | 6 - src/test/mocks/@grafana/ui.tsx | 30 - src/test/mocks/components/SimpleMap.tsx | 5 - src/test/mocks/grafana/app/core/app_events.js | 3 - .../{mocks/rawLoader.js => rawLoaderMock.js} | 0 18 files changed, 882 insertions(+), 49 deletions(-) create mode 100644 .release-it.js create mode 100644 CHANGELOG_DEPRECATED.md create mode 100644 __mocks__/@grafana/faro-web-sdk.ts create mode 100644 __mocks__/@grafana/ui.tsx create mode 100644 __mocks__/components/SimpleMap/index.tsx create mode 100644 __mocks__/grafana/app/core/app_events.ts create mode 100644 cspell.config.json create mode 100644 dummy.scss create mode 100644 src/components/Autosizer.tsx create mode 100644 src/components/__mocks__/Autosizer.tsx rename src/test/{mocks/unsupported_file.js => fileMock.js} (100%) delete mode 100644 src/test/mocks/@grafana/ui.tsx delete mode 100644 src/test/mocks/components/SimpleMap.tsx delete mode 100644 src/test/mocks/grafana/app/core/app_events.js rename src/test/{mocks/rawLoader.js => rawLoaderMock.js} (100%) diff --git a/.release-it.js b/.release-it.js new file mode 100644 index 000000000..7a044de6e --- /dev/null +++ b/.release-it.js @@ -0,0 +1,21 @@ +module.exports = { + // TODD: enable the before init hooks once grafana/toolkit can limit the jest workers + git: { + commitMessage: 'chore: update version', + tag: false, + push: false, + commit: false, + }, + github: { + release: false, + }, + npm: { + publish: false, + }, + plugins: { + '@release-it/conventional-changelog': { + preset: 'angular', + infile: 'CHANGELOG.md', + }, + }, +}; diff --git a/CHANGELOG_DEPRECATED.md b/CHANGELOG_DEPRECATED.md new file mode 100644 index 000000000..2d1fb9e92 --- /dev/null +++ b/CHANGELOG_DEPRECATED.md @@ -0,0 +1,730 @@ +## [1.3.2](https://github.com/grafana/synthetic-monitoring-app/compare/1.3.1...1.3.2) (2021-09-08) + + +### Bug Fixes + +* check type selector should be disabled on edit ([#360](https://github.com/grafana/synthetic-monitoring-app/issues/360)) ([dda165e](https://github.com/grafana/synthetic-monitoring-app/commit/dda165e6187370d2726d4db0e31b8af2fe5bfa36)) + +## [1.3.1](https://github.com/grafana/synthetic-monitoring-app/compare/1.3.0...1.3.1) (2021-08-28) + +# [1.3.0](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.30...1.3.0) (2021-08-28) + +## [1.2.30](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.29...1.2.30) (2021-08-23) + +## [1.2.29](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.28...1.2.29) (2021-08-23) + +## [1.2.28](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.27...1.2.28) (2021-08-20) + +### Bug Fixes + +- **ui:** probe label display on probes page ([#354](https://github.com/grafana/synthetic-monitoring-app/issues/354)) ([af1605f](https://github.com/grafana/synthetic-monitoring-app/commit/af1605f6560c708e2b3d4d79ab3fa16cade3f753)) + +## [1.2.27](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.26...1.2.27) (2021-08-18) + +### Bug Fixes + +- remove duplicate label field in probe editor ([#353](https://github.com/grafana/synthetic-monitoring-app/issues/353)) ([756b04e](https://github.com/grafana/synthetic-monitoring-app/commit/756b04eff028893ae1d1a5cf181832ff8a2a3eb9)) + +## [1.2.26](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.25...1.2.26) (2021-08-18) + +## [1.2.25](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.24...1.2.25) (2021-08-17) + +### Bug Fixes + +- store results of import in sm datasource from dashboard import modal ([#349](https://github.com/grafana/synthetic-monitoring-app/issues/349)) ([e5f76d9](https://github.com/grafana/synthetic-monitoring-app/commit/e5f76d9c122850d54a0a704f7e9c95ea24a0cd54)) + +## [1.2.24](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.23...1.2.24) (2021-08-12) + +### Bug Fixes + +- update welcome page designs ([#348](https://github.com/grafana/synthetic-monitoring-app/issues/348)) ([44b2de8](https://github.com/grafana/synthetic-monitoring-app/commit/44b2de86e73e7fc3e7b7b10d86f093ffd0885f07)) + +## [1.2.23](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.22...1.2.23) (2021-08-12) + +### Bug Fixes + +- showing thresholds again ([#347](https://github.com/grafana/synthetic-monitoring-app/issues/347)) ([f78dbf7](https://github.com/grafana/synthetic-monitoring-app/commit/f78dbf798a0b66192f85426db741041557fe870a)) + +## [1.2.22](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.21...1.2.22) (2021-08-11) + +### Bug Fixes + +- remove unused public control from probes page ([#346](https://github.com/grafana/synthetic-monitoring-app/issues/346)) ([95aadf0](https://github.com/grafana/synthetic-monitoring-app/commit/95aadf059f8e73b41fb317c023270d7e0575161d)) + +## [1.2.21](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.20...1.2.21) (2021-08-10) + +### Bug Fixes + +- hiding thresholds again ([#345](https://github.com/grafana/synthetic-monitoring-app/issues/345)) ([478d74b](https://github.com/grafana/synthetic-monitoring-app/commit/478d74b458ea781e97e4ede1fd86b99d90b84425)) + +## [1.2.20](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.19...1.2.20) (2021-08-10) + +### Bug Fixes + +- unhide thresholds for when API is released ([#344](https://github.com/grafana/synthetic-monitoring-app/issues/344)) ([717fd44](https://github.com/grafana/synthetic-monitoring-app/commit/717fd44fee30fe2779c4d37f461849f83e47c068)) + +## [1.2.19](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.18...1.2.19) (2021-08-09) + +### Bug Fixes + +- hide thresholds until API is up to date ([#343](https://github.com/grafana/synthetic-monitoring-app/issues/343)) ([4e52e66](https://github.com/grafana/synthetic-monitoring-app/commit/4e52e66ff83bbae11801ac58988578fa83a90937)) + +## [1.2.18](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.17...1.2.18) (2021-08-05) + +### Bug Fixes + +- set height for HorizontalGroup to satisfy firefox ([#342](https://github.com/grafana/synthetic-monitoring-app/issues/342)) ([f2d0a2d](https://github.com/grafana/synthetic-monitoring-app/commit/f2d0a2d268162baf29335a52ec6130670450d8db)) + +## [1.2.17](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.16...1.2.17) (2021-08-05) + +## [1.2.16](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.15...1.2.16) (2021-07-29) + +### Bug Fixes + +- http version 2 value ([#341](https://github.com/grafana/synthetic-monitoring-app/issues/341)) ([85ef0bf](https://github.com/grafana/synthetic-monitoring-app/commit/85ef0bf6589c299410ef9caa7940bc6ad590cc40)) + +## [1.2.15](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.14...1.2.15) (2021-07-29) + +## [1.2.14](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.13...1.2.14) (2021-07-27) + +## [1.2.13](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.12...1.2.13) (2021-07-27) + +## [1.2.12](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.11...1.2.12) (2021-07-26) + +### Bug Fixes + +- expose proxy url setting in http check form ([#334](https://github.com/grafana/synthetic-monitoring-app/issues/334)) ([bbeeeba](https://github.com/grafana/synthetic-monitoring-app/commit/bbeeeba5378a26081ab6b181c89791156f0399b3)) + +## [1.2.11](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.10...1.2.11) (2021-07-26) + +## [1.2.10](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.9...1.2.10) (2021-07-22) + +## [1.2.9](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.8...1.2.9) (2021-07-22) + +## [1.2.8](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.7...1.2.8) (2021-07-13) + +## [1.2.7](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.6...1.2.7) (2021-07-09) + +### Bug Fixes + +- make HTTP the default check type ([#330](https://github.com/grafana/synthetic-monitoring-app/issues/330)) ([bd58ce1](https://github.com/grafana/synthetic-monitoring-app/commit/bd58ce1e4ff2ab9f4496ddcc064445e8d39fecfa)) + +## [1.2.6](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.5...1.2.6) (2021-07-09) + +### Bug Fixes + +- rename the success rate panels to reachability ([#329](https://github.com/grafana/synthetic-monitoring-app/issues/329)) ([43f30d7](https://github.com/grafana/synthetic-monitoring-app/commit/43f30d717c654cbda845570246371d178fd5c266)) + +## [1.2.5](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.4...1.2.5) (2021-07-08) + +### Bug Fixes + +- add some help text around less frequent checks and alert flapping ([#328](https://github.com/grafana/synthetic-monitoring-app/issues/328)) ([6bf87d3](https://github.com/grafana/synthetic-monitoring-app/commit/6bf87d3180e724cc11da8bdde3771cea52035fa9)) + +## [1.2.4](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.3...1.2.4) (2021-07-08) + +### Bug Fixes + +- checking show advanced metrics updates usage calculation ([#327](https://github.com/grafana/synthetic-monitoring-app/issues/327)) ([8728f27](https://github.com/grafana/synthetic-monitoring-app/commit/8728f273a6a8017f7f47b952678adf910d4af734)) + +## [1.2.3](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.2...1.2.3) (2021-07-07) + +### Bug Fixes + +- fix typo in http TLS setting label ([#325](https://github.com/grafana/synthetic-monitoring-app/issues/325)) ([9093f8d](https://github.com/grafana/synthetic-monitoring-app/commit/9093f8de53e4100e7840dfe311520d3b8d4ad8d4)) + +## [1.2.2](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.1...1.2.2) (2021-06-30) + +### Bug Fixes + +- hide footer on welcome page ([#324](https://github.com/grafana/synthetic-monitoring-app/issues/324)) ([ed3b99a](https://github.com/grafana/synthetic-monitoring-app/commit/ed3b99aee24c5d4c38d02ab53b3a2cc54167b35f)) + +## [1.2.1](https://github.com/grafana/synthetic-monitoring-app/compare/1.2.0...1.2.1) (2021-06-24) + +### Bug Fixes + +- update check viz icon color ([#323](https://github.com/grafana/synthetic-monitoring-app/issues/323)) ([20367f0](https://github.com/grafana/synthetic-monitoring-app/commit/20367f04092503b636d904424c3a4a80de1e91ea)) + +# [1.2.0](https://github.com/grafana/synthetic-monitoring-app/compare/1.1.0...1.2.0) (2021-06-24) + +### Features + +- **ui:** add locations count in checks list ([#322](https://github.com/grafana/synthetic-monitoring-app/issues/322)) ([1c35f79](https://github.com/grafana/synthetic-monitoring-app/commit/1c35f79aa45085f6de072392b4f95b3a303284a9)), closes [#321](https://github.com/grafana/synthetic-monitoring-app/issues/321) + +# [1.1.0](https://github.com/grafana/synthetic-monitoring-app/compare/1.0.13...1.1.0) (2021-06-23) + +### Features + +- add an icon overlay to the check visualization to improve accessibility ([c724eab](https://github.com/grafana/synthetic-monitoring-app/commit/c724eab7aa7bfea3cd582acd9a1a2c1aa70069fd)) + +## [1.0.13](https://github.com/grafana/synthetic-monitoring-app/compare/1.0.12...1.0.13) (2021-06-16) + +### Bug Fixes + +- add backend host to plugin config page ([#316](https://github.com/grafana/synthetic-monitoring-app/issues/316)) ([07e91c0](https://github.com/grafana/synthetic-monitoring-app/commit/07e91c0a1e54dd62ea7d6de7a5251b4a291ead7b)) + +## [1.0.12](https://github.com/grafana/synthetic-monitoring-app/compare/1.0.11...1.0.12) (2021-06-16) + +### Bug Fixes + +- format dashboard log panel to include the probe name ([#314](https://github.com/grafana/synthetic-monitoring-app/issues/314)) ([8529027](https://github.com/grafana/synthetic-monitoring-app/commit/85290276382addf3df0b6fd04e2c782dd72bc064)) + +## [1.0.11](https://github.com/grafana/synthetic-monitoring-app/compare/1.0.10...1.0.11) (2021-06-15) + +## [1.0.10](https://github.com/grafana/synthetic-monitoring-app/compare/1.0.9...1.0.10) (2021-06-14) + +## [1.0.9](https://github.com/grafana/synthetic-monitoring-app/compare/1.0.7...1.0.9) (2021-06-11) + +## [1.0.7](https://github.com/grafana/synthetic-monitoring-app/compare/1.0.6...1.0.7) (2021-06-11) + +## [1.0.6](https://github.com/grafana/synthetic-monitoring-app/compare/1.0.5...1.0.6) (2021-06-11) + +## [1.0.5](https://github.com/grafana/synthetic-monitoring-app/compare/1.0.4...1.0.5) (2021-06-11) + +## [1.0.4](https://github.com/grafana/synthetic-monitoring-app/compare/1.0.3...1.0.4) (2021-06-11) + +## [1.0.3](https://github.com/grafana/synthetic-monitoring-app/compare/1.0.2...1.0.3) (2021-06-10) + +## [1.0.2](https://github.com/grafana/synthetic-monitoring-app/compare/1.0.1...1.0.2) (2021-06-10) + +## [1.0.1](https://github.com/grafana/synthetic-monitoring-app/compare/1.0.0...1.0.1) (2021-06-07) + +### Bug Fixes + +- home dashboard redirect issue ([#290](https://github.com/grafana/synthetic-monitoring-app/issues/290)) ([f10bcdd](https://github.com/grafana/synthetic-monitoring-app/commit/f10bcddede54052d3e64aaefa500a71de642dcf5)) + +# [1.0.0](https://github.com/grafana/synthetic-monitoring-app/compare/0.11.4...1.0.0) (2021-06-07) + +### Feat + +- support grafana v8 ([c27534f](https://github.com/grafana/synthetic-monitoring-app/commit/c27534fb7d8923a5207a01648751636558ff93b2)) + +### BREAKING CHANGES + +- Updates plugin to be compatible with Grafana v8 + +## [0.11.4](https://github.com/grafana/synthetic-monitoring-app/compare/0.11.3...0.11.4) (2021-06-03) + +## [0.11.3](https://github.com/grafana/synthetic-monitoring-app/compare/0.11.2...0.11.3) (2021-06-03) + +## [0.11.2](https://github.com/grafana/synthetic-monitoring-app/compare/0.11.1...0.11.2) (2021-05-28) + +## [0.11.1](https://github.com/grafana/synthetic-monitoring-app/compare/0.11.0...0.11.1) (2021-05-24) + +# [0.11.0](https://github.com/grafana/synthetic-monitoring-app/compare/0.10.2...0.11.0) (2021-05-11) + +### Features + +- add http check configuration option for endpoints with compressed responses. ([f16f42f](https://github.com/grafana/synthetic-monitoring-app/commit/f16f42f53aca19f9c904a5b089e00d05c0f1000f)) + +## [0.10.2](https://github.com/grafana/synthetic-monitoring-app/compare/0.10.1...0.10.2) (2021-05-10) + +### Bug Fixes + +- add probe success rate to context ([#269](https://github.com/grafana/synthetic-monitoring-app/issues/269)) ([46b501c](https://github.com/grafana/synthetic-monitoring-app/commit/46b501c91330ac129425ae1d7598f6cb5da81105)) + +## [0.10.1](https://github.com/grafana/synthetic-monitoring-app/compare/0.10.0...0.10.1) (2021-05-10) + +### Bug Fixes + +- show probe version in the probe list ([#268](https://github.com/grafana/synthetic-monitoring-app/issues/268)) ([b30d626](https://github.com/grafana/synthetic-monitoring-app/commit/b30d626feb79645516075cbe891b3cf704c76746)) + +# [0.10.0](https://github.com/grafana/synthetic-monitoring-app/compare/0.9.0...0.10.0) (2021-05-10) + +### Features + +- Usage endpoint ([#267](https://github.com/grafana/synthetic-monitoring-app/issues/267)) ([e26d5e1](https://github.com/grafana/synthetic-monitoring-app/commit/e26d5e1c0a1c0e833f88da2994bbcf68de1ab836)) + +# [0.9.0](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.24...0.9.0) (2021-05-04) + +### Features + +- add the ability to sort checks by success rate ([#265](https://github.com/grafana/synthetic-monitoring-app/issues/265)) ([5b69891](https://github.com/grafana/synthetic-monitoring-app/commit/5b69891e7e780a5a882e13c8463d4b98a03cb773)) + +## [0.8.24](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.23...0.8.24) (2021-05-03) + +## [0.8.23](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.22...0.8.23) (2021-04-26) + +### Bug Fixes + +- allow trailing dots in DNS targets ([#262](https://github.com/grafana/synthetic-monitoring-app/issues/262)) ([7eb3847](https://github.com/grafana/synthetic-monitoring-app/commit/7eb3847cb2ab9c6fabdf3af11e8be746d2adb1a9)) + +## [0.8.22](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.21...0.8.22) (2021-04-22) + +### Bug Fixes + +- allow disabled plugin to be enabled before prompting for bootstrapping flow ([#256](https://github.com/grafana/synthetic-monitoring-app/issues/256)) ([75f7781](https://github.com/grafana/synthetic-monitoring-app/commit/75f77815c4bbd4e2e24fa2735839558fdecfbd56)) + +## [0.8.21](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.20...0.8.21) (2021-04-20) + +## [0.8.20](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.19...0.8.20) (2021-04-20) + +## [0.8.19](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.18...0.8.19) (2021-04-16) + +### Bug Fixes + +- allow all characters in label values ([#257](https://github.com/grafana/synthetic-monitoring-app/issues/257)) ([5780876](https://github.com/grafana/synthetic-monitoring-app/commit/5780876bfcf47b7217bb5f52565d70b2354d5451)) + +## [0.8.18](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.17...0.8.18) (2021-04-12) + +### Bug Fixes + +- allow curly brackets in http url params ([#252](https://github.com/grafana/synthetic-monitoring-app/issues/252)) ([20ac472](https://github.com/grafana/synthetic-monitoring-app/commit/20ac4722fb8754dcc5fee5bb4d1eac588ec77602)) + +## [0.8.17](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.16...0.8.17) (2021-04-09) + +### Bug Fixes + +- increase label length validation to allow 128 characters ([#248](https://github.com/grafana/synthetic-monitoring-app/issues/248)) ([142f5f4](https://github.com/grafana/synthetic-monitoring-app/commit/142f5f443a165e467f616de2ebcb94b58b029dff)) + +## [0.8.16](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.15...0.8.16) (2021-04-09) + +## [0.8.15](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.14...0.8.15) (2021-03-26) + +## [0.8.14](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.13...0.8.14) (2021-03-25) + +### Bug Fixes + +- validate that labels names are not duplicated ([#246](https://github.com/grafana/synthetic-monitoring-app/issues/246)) ([78758fd](https://github.com/grafana/synthetic-monitoring-app/commit/78758fddb7395f768863201ed3414e324a8f73f2)) + +## [0.8.13](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.12...0.8.13) (2021-03-23) + +### Bug Fixes + +- add validation for label names and values, truncate long labels in the card view, and handle label deletion ([#241](https://github.com/grafana/synthetic-monitoring-app/issues/241)) ([15b0050](https://github.com/grafana/synthetic-monitoring-app/commit/15b00504bbcdc512428f725a9d73dc691946a92a)) + +## [0.8.12](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.11...0.8.12) (2021-03-17) + +### Bug Fixes + +- prevent probe editor from erroring out when form is not instantiated ([#236](https://github.com/grafana/synthetic-monitoring-app/issues/236)) ([0163b3f](https://github.com/grafana/synthetic-monitoring-app/commit/0163b3f4afd10c79494ce9425b49d6ad12e3f903)) + +## [0.8.11](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.10...0.8.11) (2021-03-12) + +### Bug Fixes + +- label cascader options were overwriting each other ([#235](https://github.com/grafana/synthetic-monitoring-app/issues/235)) ([f22eb38](https://github.com/grafana/synthetic-monitoring-app/commit/f22eb383924c44d37801114a20cb5c4c4c4cdaaf)) + +## [0.8.10](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.9...0.8.10) (2021-03-12) + +### Bug Fixes + +- prevent crashing on grafana v7.3 ([#234](https://github.com/grafana/synthetic-monitoring-app/issues/234)) ([9c5ff31](https://github.com/grafana/synthetic-monitoring-app/commit/9c5ff3180a0447be17e326dd9adc60cfb8d9f6d3)) + +## [0.8.9](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.8...0.8.9) (2021-03-09) + +### Bug Fixes + +- update percentage unit to match recording rule ([#230](https://github.com/grafana/synthetic-monitoring-app/issues/230)) ([47bc2b1](https://github.com/grafana/synthetic-monitoring-app/commit/47bc2b13db73bd0af7eac7ffcc6affe2dc20d39c)) + +## [0.8.8](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.7...0.8.8) (2021-03-08) + +### Bug Fixes + +- deduplicate label filter values ([#227](https://github.com/grafana/synthetic-monitoring-app/issues/227)) ([824474a](https://github.com/grafana/synthetic-monitoring-app/commit/824474a6538b028fd9b95d3c25bae7c74ae4d571)) + +## [0.8.7](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.6...0.8.7) (2021-03-08) + +### Bug Fixes + +- corrects alert expression wording in alert edit form ([#229](https://github.com/grafana/synthetic-monitoring-app/issues/229)) ([2e2ac62](https://github.com/grafana/synthetic-monitoring-app/commit/2e2ac6218727dc99fde7e05f443d4a64588aa7eb)) + +## [0.8.6](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.5...0.8.6) (2021-03-08) + +## [0.8.5](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.4...0.8.5) (2021-03-05) + +### Bug Fixes + +- increase job name length limit ([#223](https://github.com/grafana/synthetic-monitoring-app/issues/223)) ([720d0ca](https://github.com/grafana/synthetic-monitoring-app/commit/720d0cafc69595a3407c1c8403c390e693e53bcd)) + +## [0.8.4](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.3...0.8.4) (2021-03-04) + +## [0.8.3](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.2...0.8.3) (2021-03-02) + +### Bug Fixes + +- latency was showing centiseconds instead of milliseconds ([#220](https://github.com/grafana/synthetic-monitoring-app/issues/220)) ([e7f7e37](https://github.com/grafana/synthetic-monitoring-app/commit/e7f7e3740cfae8e9cf4546cc7e8d89e6dafc76cb)) + +## [0.8.2](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.1...0.8.2) (2021-03-02) + +## [0.8.1](https://github.com/grafana/synthetic-monitoring-app/compare/0.8.0...0.8.1) (2021-03-02) + +# [0.8.0](https://github.com/grafana/synthetic-monitoring-app/compare/0.7.18...0.8.0) (2021-03-02) + +### Features + +- Updated checks page ([2385caa](https://github.com/grafana/synthetic-monitoring-app/commit/2385caa3f23c5b95edd70d72e17de9eaab534ec7)) + +## [0.7.18](https://github.com/grafana/synthetic-monitoring-app/compare/0.7.17...0.7.18) (2021-03-01) + +### Bug Fixes + +- handle tls config with undefined cert ([#217](https://github.com/grafana/synthetic-monitoring-app/issues/217)) ([f728a18](https://github.com/grafana/synthetic-monitoring-app/commit/f728a18bb5f49a393966de62e3a0e9637e8265fe)) + +## [0.7.17](https://github.com/grafana/synthetic-monitoring-app/compare/0.7.16...0.7.17) (2021-02-26) + +### Bug Fixes + +- Add validation and messaging to enforce PEM certs for checks with TLS ([73fecca](https://github.com/grafana/synthetic-monitoring-app/commit/73fecca701ca635a457a6023e63a4174f6cab671)) + +## [0.7.16](https://github.com/grafana/synthetic-monitoring-app/compare/0.7.15...0.7.16) (2021-02-17) + +## [0.7.15](https://github.com/grafana/synthetic-monitoring-app/compare/0.7.14...0.7.15) (2021-02-17) + +### Bug Fixes + +- add plugin enable action ([#206](https://github.com/grafana/synthetic-monitoring-app/issues/206)) ([abee206](https://github.com/grafana/synthetic-monitoring-app/commit/abee206a65e4f144926a6aeb8400d5e079f89bfc)) + +## [0.7.14](https://github.com/grafana/synthetic-monitoring-app/compare/0.7.13...0.7.14) (2021-02-12) + +### Bug Fixes + +- encode/decode tls certificates to/from base 64 ([#205](https://github.com/grafana/synthetic-monitoring-app/issues/205)) ([39daa19](https://github.com/grafana/synthetic-monitoring-app/commit/39daa19bd57c0f2bedac1118b8f965c4f120ab7d)) + +## [0.7.13](https://github.com/grafana/synthetic-monitoring-app/compare/0.7.12...0.7.13) (2021-02-11) + +## [0.7.12](https://github.com/grafana/synthetic-monitoring-app/compare/0.7.11...0.7.12) (2021-02-11) + +### Bug Fixes + +- prevent clearing probes from clearing the whole form ([#203](https://github.com/grafana/synthetic-monitoring-app/issues/203)) ([a031656](https://github.com/grafana/synthetic-monitoring-app/commit/a0316568576dd360107f5eae5b9f9b531f5d560d)) + +## [0.7.11](https://github.com/grafana/synthetic-monitoring-app/compare/0.7.10...0.7.11) (2021-02-11) + +### Bug Fixes + +- remove broken config link ([#202](https://github.com/grafana/synthetic-monitoring-app/issues/202)) ([b1287e3](https://github.com/grafana/synthetic-monitoring-app/commit/b1287e35ed339cdf7c2501cade5ae6fc9a47bbee)) + +## [0.7.10](https://github.com/grafana/synthetic-monitoring-app/compare/0.7.9...0.7.10) (2021-02-11) + +## [0.7.9](https://github.com/grafana/synthetic-monitoring-app/compare/0.7.8...0.7.9) (2021-02-11) + +## [0.7.8](https://github.com/grafana/synthetic-monitoring-app/compare/0.7.7...0.7.8) (2021-02-11) + +## [0.7.7](https://github.com/grafana/synthetic-monitoring-app/compare/0.7.6...0.7.7) (2021-02-11) + +## [0.7.6](https://github.com/grafana/synthetic-monitoring-app/compare/0.7.5...0.7.6) (2021-02-11) + +## [0.7.5](https://github.com/grafana/synthetic-monitoring-app/compare/0.7.4...0.7.5) (2021-02-10) + +### Bug Fixes + +- allow hostnames that start with a number and have a subdomain ([#194](https://github.com/grafana/synthetic-monitoring-app/issues/194)) ([c9d04ec](https://github.com/grafana/synthetic-monitoring-app/commit/c9d04ec6d9640842d24f3190402b29c5cae4f68f)) + +## [0.7.4](https://github.com/grafana/synthetic-monitoring-app/compare/0.7.3...0.7.4) (2021-02-10) + +### Bug Fixes + +- Gate alerts by admin role ([#196](https://github.com/grafana/synthetic-monitoring-app/issues/196)) ([af31088](https://github.com/grafana/synthetic-monitoring-app/commit/af31088c1303e8cadba1b545a988907d24cf817b)) + +## [0.7.3](https://github.com/grafana/synthetic-monitoring-app/compare/0.7.2...0.7.3) (2021-02-10) + +## [0.7.2](https://github.com/grafana/synthetic-monitoring-app/compare/0.7.1...0.7.2) (2021-02-09) + +## [0.7.1](https://github.com/grafana/synthetic-monitoring-app/compare/0.7.0...0.7.1) (2021-02-02) + +# [0.7.0](https://github.com/grafana/synthetic-monitoring-app/compare/0.6.2...0.7.0) (2021-01-29) + +### Features + +- Add alerts ([af5b835](https://github.com/grafana/synthetic-monitoring-app/commit/af5b83575344d85688455802a74c0cfc1dad7d82)) + +## [0.6.2](https://github.com/grafana/synthetic-monitoring-app/compare/0.6.1...0.6.2) (2021-01-29) + +## [0.6.1](https://github.com/grafana/synthetic-monitoring-app/compare/0.6.0...0.6.1) (2021-01-29) + +### Bug Fixes + +- update tcp query response to send and parse base64 ([#187](https://github.com/grafana/synthetic-monitoring-app/issues/187)) ([64c096e](https://github.com/grafana/synthetic-monitoring-app/commit/64c096e062be7290efb448f008d59e030d2532f6)) + +# [0.6.0](https://github.com/grafana/synthetic-monitoring-app/compare/0.5.7...0.6.0) (2021-01-22) + +### Features + +- add field for basic metrics ([9113ffb](https://github.com/grafana/synthetic-monitoring-app/commit/9113ffb972b6a22bf5218d2db5e18a7708a6f4e4)) + +## [0.5.7](https://github.com/grafana/synthetic-monitoring-app/compare/0.5.6...0.5.7) (2021-01-14) + +### Bug Fixes + +- renavigate to checks page after deleting check ([550a14a](https://github.com/grafana/synthetic-monitoring-app/commit/550a14a2abdb6b414551260c616b198981abf1ed)) + +## [0.5.6](https://github.com/grafana/synthetic-monitoring-app/compare/0.5.5...0.5.6) (2021-01-06) + +### Bug Fixes + +- hide alerts for new checks ([#174](https://github.com/grafana/synthetic-monitoring-app/issues/174)) ([a7713f6](https://github.com/grafana/synthetic-monitoring-app/commit/a7713f638a5a552362934e1b649b3dd84e86aec2)) + +## [0.5.5](https://github.com/grafana/synthetic-monitoring-app/compare/0.5.4...0.5.5) (2020-12-30) + +### Bug Fixes + +- handle error response on welcome page ([#170](https://github.com/grafana/synthetic-monitoring-app/issues/170)) ([1e83510](https://github.com/grafana/synthetic-monitoring-app/commit/1e835101036824a078a462cee2b0e1946934e970)) + +## [0.5.4](https://github.com/grafana/synthetic-monitoring-app/compare/0.5.3...0.5.4) (2020-12-29) + +### Bug Fixes + +- add severity as an alert rule label ([#172](https://github.com/grafana/synthetic-monitoring-app/issues/172)) ([1f74994](https://github.com/grafana/synthetic-monitoring-app/commit/1f7499444160d6f70b4bf305be3de4419e590732)) + +## [0.5.3](https://github.com/grafana/synthetic-monitoring-app/compare/0.5.2...0.5.3) (2020-12-29) + +### Bug Fixes + +- annotation and labels in alerts not getting sent to ruler ([#171](https://github.com/grafana/synthetic-monitoring-app/issues/171)) ([82b1f85](https://github.com/grafana/synthetic-monitoring-app/commit/82b1f851d157ec5f2ece23295594e8f6c6627823)) + +## [0.5.2](https://github.com/grafana/synthetic-monitoring-app/compare/0.5.1...0.5.2) (2020-12-29) + +### Bug Fixes + +- allow ipv6 hostnames for http checks ([#167](https://github.com/grafana/synthetic-monitoring-app/issues/167)) ([5fa39ed](https://github.com/grafana/synthetic-monitoring-app/commit/5fa39edb0089aacdaa8aee412aebeaef49531dbc)) + +## [0.5.1](https://github.com/grafana/synthetic-monitoring-app/compare/0.5.0...0.5.1) (2020-12-29) + +# [0.5.0](https://github.com/grafana/synthetic-monitoring-app/compare/0.4.1...0.5.0) (2020-12-28) + +### Features + +- add alert creation to check editor ([3fdd8e1](https://github.com/grafana/synthetic-monitoring-app/commit/3fdd8e1572d40a868f2c4baaacbd58ffc471a840)) + +## [0.4.1](https://github.com/grafana/synthetic-monitoring-app/compare/0.4.0...0.4.1) (2020-12-10) + +### Bug Fixes + +- paginate checks ([#165](https://github.com/grafana/synthetic-monitoring-app/issues/165)) ([a571cc1](https://github.com/grafana/synthetic-monitoring-app/commit/a571cc1322d9491da28ba4ad9d45743785f93e52)) + +# [0.4.0](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.47...0.4.0) (2020-12-03) + +### Features + +- add a check usage calculator ([1c38252](https://github.com/grafana/synthetic-monitoring-app/commit/1c38252956ec58c70ddafb3aedee1acb3b5c6174)) + +## [0.3.47](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.46...0.3.47) (2020-11-25) + +## [0.3.46](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.45...0.3.46) (2020-11-25) + +### Bug Fixes + +- open docs from welcome page in a new tab ([#154](https://github.com/grafana/synthetic-monitoring-app/issues/154)) ([151a3b5](https://github.com/grafana/synthetic-monitoring-app/commit/151a3b58f0586c1f0ed373c07a28a3a924c1ec76)) + +## [0.3.45](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.44...0.3.45) (2020-11-10) + +### Bug Fixes + +- handle preexisting datasources ([#151](https://github.com/grafana/synthetic-monitoring-app/issues/151)) ([9c6e56b](https://github.com/grafana/synthetic-monitoring-app/commit/9c6e56b151784f390dbd9b4c51a72bdfab9edddd)) + +## [0.3.44](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.43...0.3.44) (2020-11-10) + +## [0.3.43](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.42...0.3.43) (2020-11-09) + +### Bug Fixes + +- change stackId provisioning name ([#149](https://github.com/grafana/synthetic-monitoring-app/issues/149)) ([fd818ac](https://github.com/grafana/synthetic-monitoring-app/commit/fd818ac0662123f79f25a77977ddcdeeb5c5e6a7)) + +## [0.3.42](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.41...0.3.42) (2020-11-09) + +### Bug Fixes + +- handle unprovisioned cloud bootstrapping ([#148](https://github.com/grafana/synthetic-monitoring-app/issues/148)) ([9580267](https://github.com/grafana/synthetic-monitoring-app/commit/9580267593338517532ac8a810a4af07fad144ba)) + +## [0.3.41](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.40...0.3.41) (2020-11-09) + +### Bug Fixes + +- legend displays "Value" instead of probe name ([#147](https://github.com/grafana/synthetic-monitoring-app/issues/147)) ([7fbbfba](https://github.com/grafana/synthetic-monitoring-app/commit/7fbbfbafbdc42cf11464f3feedba97aff072d9c0)), closes [#146](https://github.com/grafana/synthetic-monitoring-app/issues/146) + +## [0.3.40](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.39...0.3.40) (2020-11-04) + +### Bug Fixes + +- update probe locations description typo ([#140](https://github.com/grafana/synthetic-monitoring-app/issues/140)) ([3840323](https://github.com/grafana/synthetic-monitoring-app/commit/384032323a876e7ef7ed561f9309ef85359cf93e)) + +## [0.3.39](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.38...0.3.39) (2020-10-27) + +### Bug Fixes + +- handle http regex validation value deletion bug ([dd01f12](https://github.com/grafana/synthetic-monitoring-app/commit/dd01f1248cbe51de4d107a7cd319450ad69ea20f)) + +## [0.3.38](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.37...0.3.38) (2020-10-27) + +### Bug Fixes + +- header validations in http checks persisting incorrectly ([3db912c](https://github.com/grafana/synthetic-monitoring-app/commit/3db912ca84db75e7d75726a9c411554b6fb2f1dd)) + +## [0.3.37](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.36...0.3.37) (2020-10-20) + +### Bug Fixes + +- add dashboard update modal ([bce8d75](https://github.com/grafana/synthetic-monitoring-app/commit/bce8d753f2875e4980766a7d93706b93c450cf5c)) +- auto update dashboards on UI load ([a5293a5](https://github.com/grafana/synthetic-monitoring-app/commit/a5293a58028761ea8dbf910156225b701a27dded)) + +## [0.3.36](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.35...0.3.36) (2020-10-16) + +### Bug Fixes + +- update queries for metrics used in the UI ([34bfa7d](https://github.com/grafana/synthetic-monitoring-app/commit/34bfa7da658eff10e07a8c92a9b3e1839bf0620d)) +- update TCP queries to use old and new metric names ([120696f](https://github.com/grafana/synthetic-monitoring-app/commit/120696f7bd51438f2417c1af6a5fb83dff3fa38a)) + +## [0.3.35](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.34...0.3.35) (2020-10-16) + +### Bug Fixes + +- update queries that use the renamed metrics ([798c183](https://github.com/grafana/synthetic-monitoring-app/commit/798c183bf763625dcb79a31d13f0df10009a51fb)) + +## [0.3.34](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.33...0.3.34) (2020-10-15) + +### Bug Fixes + +- send a no-cache header when fetching dashboards ([53d6f8a](https://github.com/grafana/synthetic-monitoring-app/commit/53d6f8a3658ccbf464adc73bcb81eb6d5ee102f3)) + +## [0.3.33](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.32...0.3.33) (2020-10-15) + +## [0.3.32](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.31...0.3.32) (2020-10-15) + +## [0.3.31](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.30...0.3.31) (2020-10-14) + +### Bug Fixes + +- use new metric names ([#114](https://github.com/grafana/synthetic-monitoring-app/issues/114)) ([35fea5e](https://github.com/grafana/synthetic-monitoring-app/commit/35fea5e1de2945358ce611414f0f051494b644dc)) + +## [0.3.30](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.29...0.3.30) (2020-10-14) + +### Bug Fixes + +- allow floats in probe lat/long ([d58f872](https://github.com/grafana/synthetic-monitoring-app/commit/d58f87215999f307680799a76e5040023b53acc0)) + +## [0.3.29](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.28...0.3.29) (2020-10-12) + +## [0.3.28](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.27...0.3.28) (2020-10-12) + +## [0.3.27](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.26...0.3.27) (2020-10-09) + +### Bug Fixes + +- allow hostnames to start with a number ([275070f](https://github.com/grafana/synthetic-monitoring-app/commit/275070fbd1f1c9d00260524609e633139e83370b)) + +## [0.3.26](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.25...0.3.26) (2020-10-02) + +## [0.3.25](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.24...0.3.25) (2020-10-01) + +## [0.3.24](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.23...0.3.24) (2020-09-29) + +### Bug Fixes + +- specify a step size for slider input ([ec2fe5c](https://github.com/grafana/synthetic-monitoring-app/commit/ec2fe5ccda7943b14c8ffacfe6a045e21a5645c0)) + +## [0.3.23](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.22...0.3.23) (2020-09-29) + +## [0.3.22](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.21...0.3.22) (2020-09-29) + +## [0.3.21](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.20...0.3.21) (2020-09-29) + +## [0.3.20](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.19...0.3.20) (2020-09-29) + +## [0.3.19](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.18...0.3.19) (2020-09-29) + +## [0.3.18](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.17...0.3.18) (2020-09-29) + +## [0.3.17](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.16...0.3.17) (2020-09-29) + +## [0.3.16](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.15...0.3.16) (2020-09-29) + +## [0.3.15](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.14...0.3.15) (2020-09-29) + +## [0.3.14](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.13...0.3.14) (2020-09-28) + +## [0.3.13](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.12...0.3.13) (2020-09-28) + +## [0.3.12](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.11...0.3.12) (2020-09-28) + +## [0.3.11](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.10...0.3.11) (2020-09-28) + +## [0.3.10](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.9...0.3.10) (2020-09-25) + +## [0.3.9](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.8...0.3.9) (2020-09-25) + +### Bug Fixes + +- stuck loading spinner on check creation ([d9a77ba](https://github.com/grafana/synthetic-monitoring-app/commit/d9a77ba12e3e355ad79eca820ed3615fd5e31534)) + +## [0.3.8](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.7...0.3.8) (2020-09-25) + +## [0.3.7](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.6...0.3.7) (2020-09-25) + +## [0.3.6](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.5...0.3.6) (2020-09-25) + +## [0.3.5](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.4...0.3.5) (2020-09-25) + +## [0.3.4](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.3...0.3.4) (2020-09-25) + +### Bug Fixes + +- invert noFollowRedirects in the UI ([c6d302e](https://github.com/grafana/synthetic-monitoring-app/commit/c6d302e713c4faed9c3c7c34d3560e66d72ec888)) +- make default values consistent for all check types ([56866bb](https://github.com/grafana/synthetic-monitoring-app/commit/56866bb77153ee7880f9f19b9b152db4c19a9b7c)) + +## [0.3.3](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.2...0.3.3) (2020-09-24) + +## [0.3.2](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.1...0.3.2) (2020-09-23) + +### Bug Fixes + +- fix http follow redirect setting being unresponsive ([14ca222](https://github.com/grafana/synthetic-monitoring-app/commit/14ca2227a206ec032f9befdd445b99db11dabc04)) + +## [0.3.1](https://github.com/grafana/synthetic-monitoring-app/compare/0.3.0...0.3.1) (2020-09-23) + +### Bug Fixes + +- reject http targets without a valid TLD ([3339e2f](https://github.com/grafana/synthetic-monitoring-app/commit/3339e2fa374b192df3331e15a7706988dd1ca0f6)) + +# 0.3.0 (2020-09-23) + +### Features + +- Build tooling updates, no code changes + +# 0.2.0 (2020-09-23) + +### Bug Fixes + +- give feedback when probe creation or updating fails + +# 0.1.0 (2020-09-22) + +### Update to automated changelog generation + +# 0.0.11 + +- Streamline validation and SSL option fields for HTTP checks + +# 0.0.10 + +### Bug Fixes + +- include saved tls config in http settings form ([#94](https://github.com/grafana/synthetic-monitoring-app/issues/94)) ([55a54e0](https://github.com/grafana/synthetic-monitoring-app/commit/55a54e094e5eb7a4dc433e07c2cd32329cdc333a) + +### Features + +- refresh metric data on an interval ([#88](https://github.com/grafana/synthetic-monitoring-app/issues/88)) ([6e00324](https://github.com/grafana/synthetic-monitoring-app/commit/6e00324bbb5ba04d1bb80700a1f89723ad031dd1)) + +# 0.0.9 + +### Bug Fixes + +- make check search case insensitive ([0d86f26](https://github.com/grafana/synthetic-monitoring-app/commit/0d86f262139081c4c2da1565ec1ed1894c0f829e)) + +# 0.0.8 + +### Bug Fixes + +- handle editing check with no probes ([#66](https://github.com/grafana/synthetic-monitoring-app/issues/66)) ([e56f0e2](https://github.com/grafana/synthetic-monitoring-app/commit/e56f0e25bf3c76d8f221fbd26fa8bda84ff8afec) +- add missing closing to parenthesis to query ([c23b1ac](https://github.com/grafana/synthetic-monitoring-app/commit/c23b1ac453283f84bb3a984a841eb0d6650bf2d8)), closes [#59](https://github.com/grafana/synthetic-monitoring-app/issues/59) +- show error if check update/save fails ([#68](https://github.com/grafana/synthetic-monitoring-app/issues/68)) ([ec745d8](https://github.com/grafana/synthetic-monitoring-app/commit/ec745d88fd3eb468f01ec16b457cb18d2a2a9824)) + +### Features + +- query params broken out into their own inputs ([566762b](https://github.com/grafana/synthetic-monitoring-app/commit/566762b3eb0dc2a7bb261775b9f822fb6914defe)) +- split target query params off into their own inputs ([f6972d8](https://github.com/grafana/synthetic-monitoring-app/commit/f6972d83ba9a5c7deb5ba354b2c3bc0dbb6ee1e3)) + +# 0.0.1 + +- Initial Release (preview) diff --git a/__mocks__/@grafana/faro-web-sdk.ts b/__mocks__/@grafana/faro-web-sdk.ts new file mode 100644 index 000000000..e66e79e99 --- /dev/null +++ b/__mocks__/@grafana/faro-web-sdk.ts @@ -0,0 +1,11 @@ +module.exports = { + faro: { + api: { + pushMeasurement: jest.fn(() => console.log('hhhhhhiiiiii')), + pushEvent: jest.fn(), + pushError: jest.fn(), + }, + }, + isError: jest.fn(), + isObject: jest.fn(), +}; diff --git a/__mocks__/@grafana/ui.tsx b/__mocks__/@grafana/ui.tsx new file mode 100644 index 000000000..38f151da9 --- /dev/null +++ b/__mocks__/@grafana/ui.tsx @@ -0,0 +1,42 @@ +// @ts-ignore +window.__react_router_build__ = undefined; + +const ui = jest.requireActual('@grafana/ui'); +import React, { forwardRef } from 'react'; + +const Icon = forwardRef((props, ref) => ); +Icon.displayName = 'Icon'; + +interface BigValueProps { + value: { + numeric: number; + text?: string; + title?: string; + }; +} + +export function BigValue({ value }: BigValueProps) { + return ( +
+ {/* {value.numeric} */} + {value.text && {value.text}} + {value.title && } +
+ ); +} + +// Monaco does not render with jest and is stuck at "Loading..." +// There doesn't seem to be a solution to this at this point, +// mocking it instead. Related github issue: +// https://github.com/suren-atoyan/monaco-react/issues/88 +const CodeEditor = React.forwardRef((props: any, ref: any) => { + return