From 0965c6ab75027ff918de12e45f30029476c930ba Mon Sep 17 00:00:00 2001 From: Rares Mardare Date: Tue, 27 Aug 2024 12:37:30 +0300 Subject: [PATCH 01/11] Fixed deprecated imports of H/VGroup in favor of Stack (#4897) # What this PR does Closes https://github.com/grafana/irm/issues/10 --- .github/workflows/expensive-e2e-tests.yml | 4 +- .github/workflows/linting-and-tests.yml | 7 +- grafana-plugin/.eslintrc.js | 2 +- .../integrations/maintenanceMode.test.ts | 3 +- .../outgoingWebhooks/advancedWebhook.test.ts | 10 +- .../outgoingWebhooks/simpleWebhook.test.ts | 6 +- .../configuration.test.ts | 2 + .../e2e-tests/schedules/addOverride.test.ts | 8 +- .../e2e-tests/schedules/addRotation.test.ts | 10 +- .../e2e-tests/schedules/timezones.test.ts | 2 +- .../src/components/CardButton/CardButton.tsx | 7 +- .../src/components/CheatSheet/CheatSheet.tsx | 19 +- .../CursorPagination/CursorPagination.tsx | 15 +- .../FullPageError/FullPageError.tsx | 7 +- .../IntegrationContactPoint.tsx | 59 +- .../IntegrationHowToConnect.tsx | 19 +- .../IntegrationInputField.tsx | 7 +- .../IntegrationLogoWithTitle.tsx | 7 +- .../IntegrationSendDemoAlertModal.tsx | 19 +- .../LabelsTooltipBadge/LabelsTooltipBadge.tsx | 19 +- .../ManualAlertGroup/ManualAlertGroup.tsx | 10 +- .../NewScheduleSelector.tsx | 43 +- .../NonExistentUserName.tsx | 8 +- .../PageErrorHandlingWrapper.tsx | 7 +- .../components/Policy/EscalationPolicy.tsx | 8 +- .../components/Policy/NotificationPolicy.tsx | 41 +- .../ScheduleQuality/ScheduleQuality.tsx | 11 +- .../ScheduleQualityDetails.tsx | 11 +- .../ScheduleQualityProgressBar.test.tsx | 5 - .../ScheduleQualityProgressBar.test.tsx.snap | 449 ------------ grafana-plugin/src/components/Text/Text.tsx | 10 +- .../src/components/TimeRange/TimeRange.tsx | 6 +- .../components/TooltipBadge/TooltipBadge.tsx | 11 +- .../Unauthorized/Unauthorized.test.tsx | 49 -- .../components/Unauthorized/Unauthorized.tsx | 7 +- .../__snapshots__/Unauthorized.test.tsx.snap | 291 -------- .../src/components/UserGroups/UserGroups.tsx | 10 +- .../Webhooks/WebhookLastEventDetails.tsx | 11 +- .../Webhooks/WebhookLastEventTimestamp.tsx | 6 +- .../AddResponders/AddResponders.test.tsx | 106 --- .../AddResponders/AddResponders.tsx | 19 +- .../__snapshots__/AddResponders.test.tsx.snap | 672 ------------------ .../AddRespondersPopup.test.tsx | 55 -- .../AddRespondersPopup/AddRespondersPopup.tsx | 23 +- .../AddRespondersPopup.test.tsx.snap | 82 --- .../NotificationPoliciesSelect.test.tsx | 17 - .../NotificationPoliciesSelect.test.tsx.snap | 100 --- .../TeamResponder/TeamResponder.test.tsx | 5 - .../parts/TeamResponder/TeamResponder.tsx | 10 +- .../__snapshots__/TeamResponder.test.tsx.snap | 55 -- .../UserResponder/UserResponder.test.tsx | 7 - .../parts/UserResponder/UserResponder.tsx | 14 +- .../__snapshots__/UserResponder.test.tsx.snap | 112 --- .../src/containers/AlertRules/AlertRules.tsx | 6 +- .../parts/connectors/MSTeamsConnector.tsx | 7 +- .../parts/connectors/SlackConnector.tsx | 7 +- .../parts/connectors/TelegramConnector.tsx | 7 +- .../ApiTokenSettings/ApiTokenForm.tsx | 14 +- .../ApiTokenSettings/ApiTokenSettings.tsx | 6 +- .../AttachIncidentForm/AttachIncidentForm.tsx | 10 +- .../ColumnsSelectorWrapper/ColumnsModal.tsx | 38 +- .../ColumnsSelectorWrapper.tsx | 16 +- .../EditRegexpRouteTemplateModal.tsx | 23 +- .../EscalationChainCard.tsx | 42 +- .../EscalationChainForm.tsx | 6 +- .../src/containers/GSelect/GSelect.tsx | 4 +- .../GrafanaTeamSelect/GrafanaTeamSelect.tsx | 10 +- .../CollapsedIntegrationRouteDisplay.tsx | 7 +- .../ExpandedIntegrationRouteDisplay.tsx | 52 +- .../IntegrationHeartbeatForm.tsx | 24 +- .../IntegrationForm/IntegrationForm.tsx | 31 +- .../IntegrationFormContainer.tsx | 19 +- .../IntegrationLabelsForm.tsx | 50 +- .../IntegrationTemplate.tsx | 18 +- .../MSTeams/MSTeamsInstructions.tsx | 19 +- .../MaintenanceForm/MaintenanceForm.tsx | 10 +- .../MobileAppConnection.test.tsx | 33 +- .../MobileAppConnection.tsx | 23 +- .../MobileAppConnection.test.tsx.snap | 635 ----------------- .../DisconnectButton.test.tsx | 5 - .../DisconnectButton.test.tsx.snap | 18 - .../DownloadIcons/DownloadIcons.test.tsx | 12 - .../parts/DownloadIcons/DownloadIcons.tsx | 11 +- .../__snapshots__/DownloadIcons.test.tsx.snap | 88 --- .../LinkLoginButton/LinkLoginButton.test.tsx | 12 - .../parts/LinkLoginButton/LinkLoginButton.tsx | 7 +- .../LinkLoginButton.test.tsx.snap | 44 -- .../parts/QRCode/QRCode.test.tsx | 12 - .../QRCode/__snapshots__/QRCode.test.tsx.snap | 26 - .../OutgoingWebhookForm.tsx | 24 +- .../OutgoingWebhookFormFields.tsx | 2 + .../WebhookPresetBlocks.tsx | 11 +- .../OutgoingWebhookStatus.tsx | 6 +- .../PersonalNotificationSettings.tsx | 6 +- .../PluginConfigPage/PluginConfigPage.tsx | 18 +- .../PluginInitializer/PluginInitializer.tsx | 10 +- .../RemoteFilters/RemoteFilters.tsx | 4 +- .../src/containers/Rotation/Rotation.tsx | 6 +- .../containers/RotationForm/RotationForm.tsx | 96 ++- .../RotationForm/ScheduleOverrideForm.tsx | 35 +- .../containers/RotationForm/ShiftSwapForm.tsx | 31 +- .../RotationForm/parts/DateTimePicker.tsx | 6 +- .../RotationForm/parts/DeletionModal.tsx | 15 +- .../src/containers/Rotations/Rotations.tsx | 10 +- .../containers/Rotations/ScheduleFinal.tsx | 6 +- .../Rotations/ScheduleOverrides.tsx | 10 +- .../containers/Rotations/SchedulePersonal.tsx | 24 +- .../RouteLabelsDisplay/RouteLabelsDisplay.tsx | 6 +- .../containers/ScheduleForm/ScheduleForm.tsx | 20 +- .../ScheduleIcalLink/ScheduleIcalLink.tsx | 18 +- .../containers/ScheduleSlot/ScheduleSlot.tsx | 43 +- .../CompleteServiceNowConfigModal.tsx | 6 +- .../ServiceNowAuthSection.tsx | 6 +- .../ServiceNowConfigDrawer.tsx | 6 +- .../ServiceNowStatusSection.tsx | 12 +- .../ServiceNowTokenSection.tsx | 16 +- .../src/containers/TeamsList/TeamsList.tsx | 18 +- .../TelegramIntegrationButton.tsx | 11 +- .../TemplatePreview/TemplatePreview.tsx | 18 +- .../TemplateResult/TemplateResult.tsx | 19 +- .../TemplatesAlertGroupsList.tsx | 26 +- .../UserDisplay/UserDisplayWithAvatar.tsx | 7 +- .../containers/UserSettings/UserSettings.tsx | 6 +- .../parts/connectors/GoogleConnector.tsx | 7 +- .../parts/connectors/ICalConnector.tsx | 11 +- .../parts/connectors/MSTeamsConnector.tsx | 7 +- .../parts/connectors/PhoneConnector.tsx | 11 +- .../parts/connectors/SlackConnector.tsx | 7 +- .../parts/connectors/TelegramConnector.tsx | 7 +- .../CloudPhoneSettings/CloudPhoneSettings.tsx | 27 +- .../tabs/GoogleCalendar/GoogleCalendar.tsx | 40 +- .../PhoneVerification/PhoneVerification.tsx | 35 +- .../parts/tabs/SlackTab/SlackTab.tsx | 16 +- .../parts/tabs/TelegramInfo/TelegramInfo.tsx | 16 +- .../ScheduleUserDetails.tsx | 31 +- .../UsersTimezones/UsersTimezones.tsx | 18 +- .../WebhooksTemplateEditor.tsx | 18 +- .../WithPermissionControlDisplay.tsx | 7 +- .../src/models/schedule/schedule.ts | 1 + grafana-plugin/src/module.ts | 28 +- grafana-plugin/src/navbar/Header/Header.tsx | 6 +- .../escalation-chains/EscalationChains.tsx | 20 +- .../src/pages/incident/Incident.helpers.tsx | 9 +- .../src/pages/incident/Incident.tsx | 100 +-- .../src/pages/incidents/Incidents.tsx | 33 +- .../incidents/parts/IncidentSilenceModal.tsx | 6 +- .../src/pages/insights/Insights.tsx | 8 +- .../src/pages/integration/Integration.tsx | 24 +- .../pages/integration/IntegrationActions.tsx | 20 +- .../OutgoingTab/ConnectIntegrationModal.tsx | 6 +- .../ConnectedIntegrationsTable.tsx | 20 +- .../NewOutgoingWebhookDrawerContent.tsx | 6 +- .../OutgoingTab/OtherIntegrations.tsx | 10 +- .../integration/OutgoingTab/OutgoingTab.tsx | 6 +- .../OutgoingWebhookDetailsDrawerTabs.tsx | 14 +- .../OutgoingTab/OutgoingWebhookFormFields.tsx | 23 +- .../OutgoingTab/OutgoingWebhooksTable.tsx | 11 +- .../src/pages/integrations/Integrations.tsx | 44 +- .../outgoing_webhooks/OutgoingWebhooks.tsx | 12 +- .../src/pages/schedule/Schedule.tsx | 53 +- .../src/pages/schedules/Schedules.tsx | 36 +- .../pages/settings/tabs/ChatOps/ChatOps.tsx | 14 +- .../tabs/MSTeamsSettings/MSTeamsSettings.tsx | 6 +- .../tabs/SlackSettings/SlackSettings.tsx | 19 +- .../TelegramSettings/TelegramSettings.tsx | 28 +- .../pages/settings/tabs/Cloud/CloudPage.tsx | 56 +- .../tabs/LiveSettings/LiveSettingsPage.tsx | 10 +- grafana-plugin/src/pages/users/Users.tsx | 20 +- grafana-plugin/src/plugin.json | 2 +- grafana-plugin/src/utils/consts.ts | 8 + 170 files changed, 1220 insertions(+), 4110 deletions(-) delete mode 100644 grafana-plugin/src/components/ScheduleQualityDetails/__snapshots__/ScheduleQualityProgressBar.test.tsx.snap delete mode 100644 grafana-plugin/src/components/Unauthorized/Unauthorized.test.tsx delete mode 100644 grafana-plugin/src/components/Unauthorized/__snapshots__/Unauthorized.test.tsx.snap delete mode 100644 grafana-plugin/src/containers/AddResponders/AddResponders.test.tsx delete mode 100644 grafana-plugin/src/containers/AddResponders/__snapshots__/AddResponders.test.tsx.snap delete mode 100644 grafana-plugin/src/containers/AddResponders/parts/AddRespondersPopup/AddRespondersPopup.test.tsx delete mode 100644 grafana-plugin/src/containers/AddResponders/parts/AddRespondersPopup/__snapshots__/AddRespondersPopup.test.tsx.snap delete mode 100644 grafana-plugin/src/containers/AddResponders/parts/NotificationPoliciesSelect/NotificationPoliciesSelect.test.tsx delete mode 100644 grafana-plugin/src/containers/AddResponders/parts/NotificationPoliciesSelect/__snapshots__/NotificationPoliciesSelect.test.tsx.snap delete mode 100644 grafana-plugin/src/containers/AddResponders/parts/TeamResponder/__snapshots__/TeamResponder.test.tsx.snap delete mode 100644 grafana-plugin/src/containers/AddResponders/parts/UserResponder/__snapshots__/UserResponder.test.tsx.snap delete mode 100644 grafana-plugin/src/containers/MobileAppConnection/__snapshots__/MobileAppConnection.test.tsx.snap delete mode 100644 grafana-plugin/src/containers/MobileAppConnection/parts/DisconnectButton/__snapshots__/DisconnectButton.test.tsx.snap delete mode 100644 grafana-plugin/src/containers/MobileAppConnection/parts/DownloadIcons/DownloadIcons.test.tsx delete mode 100644 grafana-plugin/src/containers/MobileAppConnection/parts/DownloadIcons/__snapshots__/DownloadIcons.test.tsx.snap delete mode 100644 grafana-plugin/src/containers/MobileAppConnection/parts/LinkLoginButton/LinkLoginButton.test.tsx delete mode 100644 grafana-plugin/src/containers/MobileAppConnection/parts/LinkLoginButton/__snapshots__/LinkLoginButton.test.tsx.snap delete mode 100644 grafana-plugin/src/containers/MobileAppConnection/parts/QRCode/QRCode.test.tsx delete mode 100644 grafana-plugin/src/containers/MobileAppConnection/parts/QRCode/__snapshots__/QRCode.test.tsx.snap diff --git a/.github/workflows/expensive-e2e-tests.yml b/.github/workflows/expensive-e2e-tests.yml index 2578860158..49aa605c04 100644 --- a/.github/workflows/expensive-e2e-tests.yml +++ b/.github/workflows/expensive-e2e-tests.yml @@ -14,8 +14,8 @@ jobs: strategy: matrix: grafana_version: - - 10.1.7 - - 10.3.3 + - 10.3.0 + - latest fail-fast: false # Run one version at a time to avoid the issue when SMS notification are bundled together for multiple versions # running at the same time (the affected test is in grafana-plugin/e2e-tests/alerts/sms.test.ts) diff --git a/.github/workflows/linting-and-tests.yml b/.github/workflows/linting-and-tests.yml index 28458a0359..d943a59502 100644 --- a/.github/workflows/linting-and-tests.yml +++ b/.github/workflows/linting-and-tests.yml @@ -242,11 +242,8 @@ jobs: strategy: matrix: grafana_version: - - 10.1.7 - - 10.3.3 - # TODO: fix issues with running e2e tests against Grafana v10.2.x and latest - # - 10.2.4 - # - latest + - 10.3.0 + - latest fail-fast: false with: grafana_version: ${{ matrix.grafana_version }} diff --git a/grafana-plugin/.eslintrc.js b/grafana-plugin/.eslintrc.js index 7d13aa6b98..a4d297ec69 100644 --- a/grafana-plugin/.eslintrc.js +++ b/grafana-plugin/.eslintrc.js @@ -12,7 +12,7 @@ module.exports = { { files: ['src/**/*.{ts,tsx}'], rules: { - 'deprecation/deprecation': 'off', + 'deprecation/deprecation': 'warn', }, parserOptions: { project: './tsconfig.json', diff --git a/grafana-plugin/e2e-tests/integrations/maintenanceMode.test.ts b/grafana-plugin/e2e-tests/integrations/maintenanceMode.test.ts index 306fa4d958..1bd6a4db57 100644 --- a/grafana-plugin/e2e-tests/integrations/maintenanceMode.test.ts +++ b/grafana-plugin/e2e-tests/integrations/maintenanceMode.test.ts @@ -24,7 +24,8 @@ test.describe('maintenance mode works', () => { await page.waitForTimeout(2000); const integrationSettingsPopupElement = page .getByTestId('integration-settings-context-menu-wrapper') - .getByRole('img'); + .locator('svg'); + await integrationSettingsPopupElement.click(); /** * sometimes we need to click twice (e.g. adding the escalation chain route diff --git a/grafana-plugin/e2e-tests/outgoingWebhooks/advancedWebhook.test.ts b/grafana-plugin/e2e-tests/outgoingWebhooks/advancedWebhook.test.ts index 713cf70556..a454eeb8be 100644 --- a/grafana-plugin/e2e-tests/outgoingWebhooks/advancedWebhook.test.ts +++ b/grafana-plugin/e2e-tests/outgoingWebhooks/advancedWebhook.test.ts @@ -22,12 +22,14 @@ test('create advanced webhook and check it is displayed on the list correctly', // Enter webhook name await webhooksFormDivs.locator('[name=name]').fill(WEBHOOK_NAME); - // Select team - await page.getByLabel('New Outgoing Webhook').getByRole('img').nth(1).click(); // Open team dropdown - await page.getByLabel('Select options menu').getByText('No team').click(); // Select "No team" + // Open team dropdown + await page.getByTestId('team-selector').locator('div').filter({ hasText: 'Choose (Optional)' }).nth(1).click(); + // Set No Team + await page.getByLabel('Select options menu').getByText('No team').click(); // Select trigger type - await webhooksFormDivs.filter({ hasText: 'Trigger Type' }).getByRole('img').click(); + await page.getByTestId('triggerType-selector').locator('div').nth(1).click(); + await page.getByLabel('Select options menu').getByText('Resolved', { exact: true }).click(); // Select integration diff --git a/grafana-plugin/e2e-tests/outgoingWebhooks/simpleWebhook.test.ts b/grafana-plugin/e2e-tests/outgoingWebhooks/simpleWebhook.test.ts index 31c9da4a13..96dd9b6cbc 100644 --- a/grafana-plugin/e2e-tests/outgoingWebhooks/simpleWebhook.test.ts +++ b/grafana-plugin/e2e-tests/outgoingWebhooks/simpleWebhook.test.ts @@ -18,8 +18,12 @@ const createWebhook = async ({ page, webhookName, webhookUrl }) => { await page.keyboard.insertText(webhookUrl); await page.locator('[name=name]').fill(webhookName); - await page.getByLabel('New Outgoing Webhook').getByRole('img').nth(1).click(); // Open team dropdown + + // Open team dropdown + await page.getByTestId('team-selector').locator('div').filter({ hasText: 'Choose (Optional)' }).nth(1).click(); + // Set No Team await page.getByLabel('Select options menu').getByText('No team').click(); + await clickButton({ page, buttonText: 'Create' }); }; diff --git a/grafana-plugin/e2e-tests/pluginInitialization/configuration.test.ts b/grafana-plugin/e2e-tests/pluginInitialization/configuration.test.ts index 8be9d75bfd..1c66b63bec 100644 --- a/grafana-plugin/e2e-tests/pluginInitialization/configuration.test.ts +++ b/grafana-plugin/e2e-tests/pluginInitialization/configuration.test.ts @@ -16,6 +16,7 @@ test.describe('Plugin configuration', () => { adminRolePage: { page }, }) => { await goToGrafanaPage(page, PLUGIN_CONFIG); + await page.waitForLoadState('networkidle'); const correctURLAppliedByDefault = await page.getByTestId('oncall-api-url-input').inputValue(); // show client-side validation errors @@ -27,6 +28,7 @@ test.describe('Plugin configuration', () => { // apply back correct url and verify plugin connected again await urlInput.fill(correctURLAppliedByDefault); + await page.waitForTimeout(500); await page.getByTestId('connect-plugin').click(); await page.waitForLoadState('networkidle'); await page.getByText('Plugin is connected').waitFor(); diff --git a/grafana-plugin/e2e-tests/schedules/addOverride.test.ts b/grafana-plugin/e2e-tests/schedules/addOverride.test.ts index a741c9338a..41fccad50d 100644 --- a/grafana-plugin/e2e-tests/schedules/addOverride.test.ts +++ b/grafana-plugin/e2e-tests/schedules/addOverride.test.ts @@ -51,9 +51,13 @@ test('Fills in override time and reacts to timezone change', async ({ adminRoleP await expect(overrideEndEl.getByTestId('date-time-picker').getByRole('textbox')).toHaveValue('09:00'); async function changeDatePickerTime(element: Locator, value: string) { - await element.getByRole('img').click(); + await element.getByTestId('date-time-picker').getByRole('textbox').click(); + // set minutes to {value} - await page.locator('.rc-time-picker-panel').getByRole('button', { name: value }).first().click(); + await page.getByRole('button', { name: value }).first().click(); + + // Old way + // await page.locator('.rc-time-picker-panel').getByRole('button', { name: value }).first().click(); // set seconds to 00 await page.getByRole('button', { name: '00' }).nth(1).click(); } diff --git a/grafana-plugin/e2e-tests/schedules/addRotation.test.ts b/grafana-plugin/e2e-tests/schedules/addRotation.test.ts index 478e69033e..f5343695bf 100644 --- a/grafana-plugin/e2e-tests/schedules/addRotation.test.ts +++ b/grafana-plugin/e2e-tests/schedules/addRotation.test.ts @@ -34,9 +34,15 @@ test('Fills in Rotation time and reacts to timezone change', async ({ adminRole await expect(endEl.getByTestId('date-time-picker').getByRole('textbox')).toHaveValue('09:00'); async function changeDatePickerTime(element: Locator, value: string) { - await element.getByRole('img').click(); + await element.getByTestId('date-time-picker').getByRole('textbox').click(); + // set minutes to {value} - await page.locator('.rc-time-picker-panel').getByRole('button', { name: value }).first().click(); + await page.getByRole('button', { name: value }).first().click(); + // await page.getByRole('button', { name: seconds }).nth(1).click(); + + // Old way + // await page.locator('.rc-time-picker-panel').getByRole('button', { name: value }).first().click(); + // set seconds to 00 await page.getByRole('button', { name: '00' }).nth(1).click(); } diff --git a/grafana-plugin/e2e-tests/schedules/timezones.test.ts b/grafana-plugin/e2e-tests/schedules/timezones.test.ts index 71df96f620..4f69839623 100644 --- a/grafana-plugin/e2e-tests/schedules/timezones.test.ts +++ b/grafana-plugin/e2e-tests/schedules/timezones.test.ts @@ -30,7 +30,7 @@ test('dates in schedule are correct according to selected current timezone', asy await expect(page.getByTestId('timezone-select')).toHaveText('GMT+3'); // Change timezone to GMT - await page.getByTestId('timezone-select').getByRole('img').click(); + await page.getByTestId('timezone-select').locator('div').filter({ hasText: 'GMT+' }).nth(1).click(); await page.getByText('GMT', { exact: true }).click(); // Selected timezone and local time is correctly displayed diff --git a/grafana-plugin/src/components/CardButton/CardButton.tsx b/grafana-plugin/src/components/CardButton/CardButton.tsx index c7a3303edf..e0b0355770 100644 --- a/grafana-plugin/src/components/CardButton/CardButton.tsx +++ b/grafana-plugin/src/components/CardButton/CardButton.tsx @@ -1,10 +1,11 @@ import React, { FC } from 'react'; import { cx } from '@emotion/css'; -import { VerticalGroup, useStyles2 } from '@grafana/ui'; +import { Stack, useStyles2 } from '@grafana/ui'; import { Block } from 'components/GBlock/Block'; import { Text } from 'components/Text/Text'; +import { StackSize } from 'utils/consts'; import { getCardButtonStyles } from './CardButton.styles'; @@ -30,10 +31,10 @@ export const CardButton: FC = (props) => { >
{icon}
- + {description} {title} - +
); diff --git a/grafana-plugin/src/components/CheatSheet/CheatSheet.tsx b/grafana-plugin/src/components/CheatSheet/CheatSheet.tsx index e2ad6d5b0a..bb28a07ba6 100644 --- a/grafana-plugin/src/components/CheatSheet/CheatSheet.tsx +++ b/grafana-plugin/src/components/CheatSheet/CheatSheet.tsx @@ -1,11 +1,12 @@ import React from 'react'; -import { HorizontalGroup, IconButton, VerticalGroup, useStyles2 } from '@grafana/ui'; +import { IconButton, Stack, useStyles2 } from '@grafana/ui'; import CopyToClipboard from 'react-copy-to-clipboard'; import { bem, getUtilStyles } from 'styles/utils.styles'; import { Block } from 'components/GBlock/Block'; import { Text } from 'components/Text/Text'; +import { StackSize } from 'utils/consts'; import { openNotification } from 'utils/utils'; import { CheatSheetInterface, CheatSheetItem } from './CheatSheet.config'; @@ -26,11 +27,11 @@ export const CheatSheet = (props: CheatSheetProps) => { return (
- - + + {cheatSheetName} cheatsheet - + {cheatSheetData.description}
{cheatSheetData.fields?.map((field: CheatSheetItem) => { @@ -41,7 +42,7 @@ export const CheatSheet = (props: CheatSheetProps) => { ); })}
-
+
); @@ -60,7 +61,7 @@ const CheatSheetListItem = (props: CheatSheetListItemProps) => { {field.listItems?.map((item, key) => { return (
- + {item.listItemName && (
  • {item.listItemName} @@ -69,18 +70,18 @@ const CheatSheetListItem = (props: CheatSheetListItemProps) => { {item.codeExample && (
    - + {item.codeExample} openNotification('Example copied')}> - +
    )} - +
  • ); })} diff --git a/grafana-plugin/src/components/CursorPagination/CursorPagination.tsx b/grafana-plugin/src/components/CursorPagination/CursorPagination.tsx index 20a50ea24d..a24eb49a09 100644 --- a/grafana-plugin/src/components/CursorPagination/CursorPagination.tsx +++ b/grafana-plugin/src/components/CursorPagination/CursorPagination.tsx @@ -1,9 +1,10 @@ import React, { FC, useCallback, useEffect, useState } from 'react'; import { SelectableValue } from '@grafana/data'; -import { Button, HorizontalGroup, Icon, Select } from '@grafana/ui'; +import { Button, Icon, Select, Stack } from '@grafana/ui'; import { Text } from 'components/Text/Text'; +import { StackSize } from 'utils/consts'; interface CursorPaginationProps { current: string; @@ -30,8 +31,8 @@ export const CursorPagination: FC = (props) => { }, []); return ( - - + + Items per list ({ label: option.display_name, value: option.value }))} @@ -86,7 +77,7 @@ export class NotificationPolicy extends React.Component -
    +
    = observer(({ schedule }) text={schedule.number_of_escalation_chains} tooltipTitle="Used in escalations" tooltipContent={ - + {relatedScheduleEscalationChains.map((escalationChain) => (
    @@ -58,7 +59,7 @@ export const ScheduleQuality: FC = observer(({ schedule })
    ))} -
    + } /> )} @@ -71,13 +72,13 @@ export const ScheduleQuality: FC = observer(({ schedule }) text={schedule.warnings.length} tooltipTitle="Warnings" tooltipContent={ - + {schedule.warnings.map((warning, index) => ( {warning} ))} - + } /> )} diff --git a/grafana-plugin/src/components/ScheduleQualityDetails/ScheduleQualityDetails.tsx b/grafana-plugin/src/components/ScheduleQualityDetails/ScheduleQualityDetails.tsx index 43e9f3cddb..ec36031818 100644 --- a/grafana-plugin/src/components/ScheduleQualityDetails/ScheduleQualityDetails.tsx +++ b/grafana-plugin/src/components/ScheduleQualityDetails/ScheduleQualityDetails.tsx @@ -1,11 +1,12 @@ import React, { FC, useCallback, useState } from 'react'; import { cx } from '@emotion/css'; -import { HorizontalGroup, Icon, IconButton, useStyles2 } from '@grafana/ui'; +import { Icon, IconButton, Stack, useStyles2 } from '@grafana/ui'; import { bem, getUtilStyles } from 'styles/utils.styles'; import { Text } from 'components/Text/Text'; import { ScheduleScoreQualityResponse, ScheduleScoreQualityResult } from 'models/schedule/schedule.types'; +import { StackSize } from 'utils/consts'; import { getScheduleQualityDetailsStyles } from './ScheduleQualityDetails.styles'; import { ScheduleQualityProgressBar } from './ScheduleQualityProgressBar'; @@ -112,19 +113,19 @@ export const ScheduleQualityDetails: FC = ({ qualit bem(styles.container, 'withLateralPadding') )} > - - + + Calculation methodology - + - + {expanded && ( The next 52 weeks (~1 year) are taken into account when generating the quality report. Refer to the{' '} diff --git a/grafana-plugin/src/components/ScheduleQualityDetails/ScheduleQualityProgressBar.test.tsx b/grafana-plugin/src/components/ScheduleQualityDetails/ScheduleQualityProgressBar.test.tsx index 764edb70b5..265d24088a 100644 --- a/grafana-plugin/src/components/ScheduleQualityDetails/ScheduleQualityProgressBar.test.tsx +++ b/grafana-plugin/src/components/ScheduleQualityDetails/ScheduleQualityProgressBar.test.tsx @@ -27,11 +27,6 @@ describe('SourceCode', () => { allBars.forEach((bar) => expect(bar.getAttribute('style').includes('width: 100%'))); }); - test.each([0, 25, 30, 50, 65, 70, 100])('It renders at %p%', (completed) => { - const component = render(); - expect(component.container).toMatchSnapshot(); - }); - test.each([0, 10, 19])('It renders as danger at <20% completion', (completed) => { render(); diff --git a/grafana-plugin/src/components/ScheduleQualityDetails/__snapshots__/ScheduleQualityProgressBar.test.tsx.snap b/grafana-plugin/src/components/ScheduleQualityDetails/__snapshots__/ScheduleQualityProgressBar.test.tsx.snap deleted file mode 100644 index 6795133fe9..0000000000 --- a/grafana-plugin/src/components/ScheduleQualityDetails/__snapshots__/ScheduleQualityProgressBar.test.tsx.snap +++ /dev/null @@ -1,449 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`SourceCode It renders at 0% 1`] = ` -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -`; - -exports[`SourceCode It renders at 25% 1`] = ` -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -`; - -exports[`SourceCode It renders at 30% 1`] = ` -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -`; - -exports[`SourceCode It renders at 50% 1`] = ` -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -`; - -exports[`SourceCode It renders at 65% 1`] = ` -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -`; - -exports[`SourceCode It renders at 70% 1`] = ` -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -`; - -exports[`SourceCode It renders at 100% 1`] = ` -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -`; diff --git a/grafana-plugin/src/components/Text/Text.tsx b/grafana-plugin/src/components/Text/Text.tsx index de2857d17e..b78f4b6084 100644 --- a/grafana-plugin/src/components/Text/Text.tsx +++ b/grafana-plugin/src/components/Text/Text.tsx @@ -1,7 +1,7 @@ import React, { FC, HTMLAttributes, ChangeEvent, useState, useCallback } from 'react'; import { cx } from '@emotion/css'; -import { IconButton, Modal, Input, HorizontalGroup, Button, VerticalGroup, useStyles2 } from '@grafana/ui'; +import { IconButton, Modal, Input, Button, Stack, useStyles2 } from '@grafana/ui'; import CopyToClipboard from 'react-copy-to-clipboard'; import { bem } from 'styles/utils.styles'; @@ -138,7 +138,7 @@ export const Text: TextInterface = (props) => { )} {isEditMode && ( - + { @@ -149,15 +149,15 @@ export const Text: TextInterface = (props) => { value={value} onChange={handleInputChange} /> - + - - + + )} diff --git a/grafana-plugin/src/components/TimeRange/TimeRange.tsx b/grafana-plugin/src/components/TimeRange/TimeRange.tsx index d5c4ae307d..7ede7c6e7d 100644 --- a/grafana-plugin/src/components/TimeRange/TimeRange.tsx +++ b/grafana-plugin/src/components/TimeRange/TimeRange.tsx @@ -1,7 +1,7 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { css, cx } from '@emotion/css'; -import { HorizontalGroup, TimeOfDayPicker, useStyles2 } from '@grafana/ui'; +import { Stack, TimeOfDayPicker, useStyles2 } from '@grafana/ui'; import moment from 'moment-timezone'; interface TimeRangeProps { @@ -94,7 +94,7 @@ export const TimeRange = (props: TimeRangeProps) => { return (
    - +
    {/* @ts-ignore actually TimeOfDayPicker uses Moment objects */} @@ -105,7 +105,7 @@ export const TimeRange = (props: TimeRangeProps) => {
    {showNextDayTip && 'next day'} -
    +
    ); }; diff --git a/grafana-plugin/src/components/TooltipBadge/TooltipBadge.tsx b/grafana-plugin/src/components/TooltipBadge/TooltipBadge.tsx index 888170e20d..9678d17da7 100644 --- a/grafana-plugin/src/components/TooltipBadge/TooltipBadge.tsx +++ b/grafana-plugin/src/components/TooltipBadge/TooltipBadge.tsx @@ -1,10 +1,11 @@ import React, { FC } from 'react'; import { cx } from '@emotion/css'; -import { Icon, Tooltip, IconName, VerticalGroup, HorizontalGroup, useStyles2 } from '@grafana/ui'; +import { Icon, Tooltip, IconName, Stack, useStyles2 } from '@grafana/ui'; import { bem } from 'styles/utils.styles'; import { Text, TextType } from 'components/Text/Text'; +import { StackSize } from 'utils/consts'; import { getTooltipBadgeStyles } from './TooltipBadge.styles'; @@ -47,10 +48,10 @@ export const TooltipBadge: FC = (props) => { interactive content={
    - + {tooltipTitle} {tooltipContent && {tooltipContent}} - +
    } > @@ -59,10 +60,10 @@ export const TooltipBadge: FC = (props) => { onMouseEnter={onHover} {...(testId ? { 'data-testid': testId } : {})} > - + {renderIcon()} {text !== undefined && {text}} - +
    ); diff --git a/grafana-plugin/src/components/Unauthorized/Unauthorized.test.tsx b/grafana-plugin/src/components/Unauthorized/Unauthorized.test.tsx deleted file mode 100644 index c3ca5b7e76..0000000000 --- a/grafana-plugin/src/components/Unauthorized/Unauthorized.test.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import React from 'react'; - -import { OrgRole } from '@grafana/data'; -import { contextSrv } from 'grafana/app/core/core'; -import renderer from 'react-test-renderer'; - -import { Unauthorized } from 'components/Unauthorized/Unauthorized'; -import { getPluginId } from 'utils/consts'; - -jest.mock('grafana/app/core/core', () => ({ - contextSrv: { - accessControlEnabled: (): boolean => null, - }, -})); - -describe('Unauthorized', () => { - test.each([true, false])('renders properly - access control enabled: %s', (accessControlEnabled) => { - contextSrv.licensedAccessControlEnabled = () => accessControlEnabled; - const tree = renderer - .create( - - ) - .toJSON(); - expect(tree).toMatchSnapshot(); - }); - - test.each([OrgRole.Admin, OrgRole.Editor, OrgRole.Viewer])( - 'renders properly the grammar for different roles - %s', - (role) => { - contextSrv.licensedAccessControlEnabled = () => false; - const tree = renderer - .create( - - ) - .toJSON(); - expect(tree).toMatchSnapshot(); - } - ); -}); diff --git a/grafana-plugin/src/components/Unauthorized/Unauthorized.tsx b/grafana-plugin/src/components/Unauthorized/Unauthorized.tsx index cdb4ed25e7..31929e6564 100644 --- a/grafana-plugin/src/components/Unauthorized/Unauthorized.tsx +++ b/grafana-plugin/src/components/Unauthorized/Unauthorized.tsx @@ -2,11 +2,12 @@ import React, { FC } from 'react'; import { css } from '@emotion/css'; import { GrafanaTheme2, OrgRole } from '@grafana/data'; -import { VerticalGroup, useStyles2 } from '@grafana/ui'; +import { Stack, useStyles2 } from '@grafana/ui'; import { contextSrv } from 'grafana/app/core/core'; import { Text } from 'components/Text/Text'; import { UserAction } from 'utils/authorization/authorization'; +import { StackSize } from 'utils/consts'; type Props = { requiredUserAction: UserAction; @@ -17,7 +18,7 @@ export const Unauthorized: FC = ({ requiredUserAction: { permission, fall return (
    - + 403 @@ -32,7 +33,7 @@ export const Unauthorized: FC = ({ requiredUserAction: { permission, fall
    Please contact your organization administrator to request access. -
    +
    ); }; diff --git a/grafana-plugin/src/components/Unauthorized/__snapshots__/Unauthorized.test.tsx.snap b/grafana-plugin/src/components/Unauthorized/__snapshots__/Unauthorized.test.tsx.snap deleted file mode 100644 index 42ff8aa004..0000000000 --- a/grafana-plugin/src/components/Unauthorized/__snapshots__/Unauthorized.test.tsx.snap +++ /dev/null @@ -1,291 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Unauthorized renders properly - access control enabled: false 1`] = ` -
    -
    -
    -

    - - 403 - -

    -
    -
    -

    - - You do not have access to view this page. - - You must be at least an Admin. -
    -
    - Please contact your organization administrator to request access. -
    -

    -
    -
    -
    -`; - -exports[`Unauthorized renders properly - access control enabled: true 1`] = ` -
    -
    -
    -

    - - 403 - -

    -
    -
    -

    - - You do not have access to view this page. - - You are missing the grafana-oncall-app.testing:hi permission. -
    -
    - Please contact your organization administrator to request access. -
    -

    -
    -
    -
    -`; - -exports[`Unauthorized renders properly the grammar for different roles - Admin 1`] = ` -
    -
    -
    -

    - - 403 - -

    -
    -
    -

    - - You do not have access to view this page. - - You must be at least an Admin. -
    -
    - Please contact your organization administrator to request access. -
    -

    -
    -
    -
    -`; - -exports[`Unauthorized renders properly the grammar for different roles - Editor 1`] = ` -
    -
    -
    -

    - - 403 - -

    -
    -
    -

    - - You do not have access to view this page. - - You must be at least an Editor. -
    -
    - Please contact your organization administrator to request access. -
    -

    -
    -
    -
    -`; - -exports[`Unauthorized renders properly the grammar for different roles - Viewer 1`] = ` -
    -
    -
    -

    - - 403 - -

    -
    -
    -

    - - You do not have access to view this page. - - You must be at least a Viewer. -
    -
    - Please contact your organization administrator to request access. -
    -

    -
    -
    -
    -`; diff --git a/grafana-plugin/src/components/UserGroups/UserGroups.tsx b/grafana-plugin/src/components/UserGroups/UserGroups.tsx index 42373d384b..5478b956fe 100644 --- a/grafana-plugin/src/components/UserGroups/UserGroups.tsx +++ b/grafana-plugin/src/components/UserGroups/UserGroups.tsx @@ -1,7 +1,7 @@ import React, { useCallback, useEffect, useMemo, useRef } from 'react'; import { cx } from '@emotion/css'; -import { VerticalGroup, HorizontalGroup, IconButton, useStyles2 } from '@grafana/ui'; +import { Stack, IconButton, useStyles2 } from '@grafana/ui'; import { arrayMoveImmutable } from 'array-move'; import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc'; import { bem } from 'styles/utils.styles'; @@ -99,7 +99,7 @@ export const UserGroups = (props: UserGroupsProps) => { {renderUser(item.data)} {!disabled && (
    - + { onClick={getDeleteItemHandler(index)} /> - +
    )} @@ -115,7 +115,7 @@ export const UserGroups = (props: UserGroupsProps) => { return (
    - + {!disabled && ( { useDragHandle allowCreate={!disabled} /> - +
    ); }; diff --git a/grafana-plugin/src/components/Webhooks/WebhookLastEventDetails.tsx b/grafana-plugin/src/components/Webhooks/WebhookLastEventDetails.tsx index 5a03383006..0606becb5e 100644 --- a/grafana-plugin/src/components/Webhooks/WebhookLastEventDetails.tsx +++ b/grafana-plugin/src/components/Webhooks/WebhookLastEventDetails.tsx @@ -2,7 +2,7 @@ import React, { FC, useMemo } from 'react'; import { css } from '@emotion/css'; import { GrafanaTheme2 } from '@grafana/data'; -import { VerticalGroup, HorizontalGroup, Badge, useStyles2, useTheme2 } from '@grafana/ui'; +import { Stack, Badge, useStyles2, useTheme2 } from '@grafana/ui'; import dayjs from 'dayjs'; import { SourceCode } from 'components/SourceCode/SourceCode'; @@ -10,6 +10,7 @@ import { Tabs } from 'components/Tabs/Tabs'; import { Text } from 'components/Text/Text'; import { getTzOffsetString } from 'models/timezone/timezone.helpers'; import { ApiSchemas } from 'network/oncall-api/api.types'; +import { StackSize } from 'utils/consts'; import { WebhookStatusCodeBadge } from './WebhookStatusCodeBadge'; @@ -41,14 +42,14 @@ export const WebhookLastEventDetails: FC = ({ webh return ( <>
    - + {rows.map(({ title, value }) => ( - + {title} {value} - + ))} - +
    + openDrawer('webhookDetails')} /> - + ); }; diff --git a/grafana-plugin/src/containers/AddResponders/AddResponders.test.tsx b/grafana-plugin/src/containers/AddResponders/AddResponders.test.tsx deleted file mode 100644 index 9ad2ec75d1..0000000000 --- a/grafana-plugin/src/containers/AddResponders/AddResponders.test.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import React from 'react'; - -import { render } from '@testing-library/react'; -import { Provider } from 'mobx-react'; - -import { AddResponders } from './AddResponders'; - -jest.mock('./parts/AddRespondersPopup/AddRespondersPopup', () => ({ - __esModule: true, - AddRespondersPopup: () =>
    AddRespondersPopup
    , -})); - -jest.mock('containers/WithPermissionControl/WithPermissionControlTooltip', () => ({ - WithPermissionControlTooltip: ({ children }) =>
    {children}
    , -})); - -describe('AddResponders', () => { - const generateRemovePreviouslyPagedUserCallback = jest.fn(); - - test.each<'create' | 'update'>(['create', 'update'])('should render properly in %s mode', (mode) => { - const mockStoreValue = { - directPagingStore: { - selectedTeamResponder: null, - selectedUserResponders: [], - }, - }; - - const component = render( - - - - ); - expect(component.container).toMatchSnapshot(); - }); - - test.each([true, false])( - 'should properly display the add responders button when hideAddResponderButton is %s', - (hideAddResponderButton) => { - const mockStoreValue = { - directPagingStore: { - selectedTeamResponder: null, - selectedUserResponders: [], - }, - }; - - const component = render( - - - - ); - expect(component.container).toMatchSnapshot(); - } - ); - - test('should render selected team and users properly', () => { - const mockStoreValue = { - directPagingStore: { - selectedTeamResponder: { - id: 'asdfasdf', - avatar_url: 'https://example.com', - name: 'my test team', - }, - selectedUserResponders: [ - { - data: { - pk: 'mcvnm', - avatar: 'https://example.com/user123.png', - username: 'my test user', - }, - }, - { - data: { - pk: 'iuo', - avatar: 'https://example.com/user456.png', - username: 'my test user2', - }, - }, - ], - }, - }; - - const component = render( - - - - ); - expect(component.container).toMatchSnapshot(); - }); -}); diff --git a/grafana-plugin/src/containers/AddResponders/AddResponders.tsx b/grafana-plugin/src/containers/AddResponders/AddResponders.tsx index 1399bca8a2..f72b0cd765 100644 --- a/grafana-plugin/src/containers/AddResponders/AddResponders.tsx +++ b/grafana-plugin/src/containers/AddResponders/AddResponders.tsx @@ -1,7 +1,7 @@ import React, { useState, useCallback, useMemo } from 'react'; import { SelectableValue } from '@grafana/data'; -import { HorizontalGroup, Button, Modal, Alert, VerticalGroup, Icon, useStyles2 } from '@grafana/ui'; +import { Button, Modal, Alert, Stack, Icon, useStyles2 } from '@grafana/ui'; import dayjs from 'dayjs'; import { observer } from 'mobx-react'; @@ -12,6 +12,7 @@ import { UserHelper } from 'models/user/user.helpers'; import { ApiSchemas } from 'network/oncall-api/api.types'; import { useStore } from 'state/useStore'; import { UserActions } from 'utils/authorization/authorization'; +import { StackSize } from 'utils/consts'; import { getAddRespondersStyles } from './AddResponders.styles'; import { NotificationPolicyValue, UserResponder as UserResponderType } from './AddResponders.types'; @@ -38,10 +39,10 @@ const LearnMoreAboutNotificationPoliciesLink: React.FC = () => { rel="noreferrer" > - + Learn more - + ); @@ -111,7 +112,7 @@ export const AddResponders = observer( <>
    - + Participants @@ -128,7 +129,7 @@ export const AddResponders = observer( )} - + {(selectedTeamResponder || existingPagedUsers.length > 0 || selectedUserResponders.length > 0) && ( <>
      @@ -189,7 +190,7 @@ export const AddResponders = observer( onDismiss={closeUserConfirmationModal} className={styles.confirmParticipantInvitationModal} > - + {!isCreateMode && (
      @@ -213,15 +214,15 @@ export const AddResponders = observer( title="This user is not currently on-call. We don't recommend to page users outside on-call hours." /> )} - + - - + + )} diff --git a/grafana-plugin/src/containers/AddResponders/__snapshots__/AddResponders.test.tsx.snap b/grafana-plugin/src/containers/AddResponders/__snapshots__/AddResponders.test.tsx.snap deleted file mode 100644 index ed844776b1..0000000000 --- a/grafana-plugin/src/containers/AddResponders/__snapshots__/AddResponders.test.tsx.snap +++ /dev/null @@ -1,672 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`AddResponders should properly display the add responders button when hideAddResponderButton is false 1`] = ` -
      -
      -
      -
      -
      -

      - - Participants - -

      -
      -
      -
      - -
      -
      -
      -
      -
      - AddRespondersPopup -
      -
      -
      -`; - -exports[`AddResponders should properly display the add responders button when hideAddResponderButton is true 1`] = ` -
      -
      -
      -
      -
      -

      - - Participants - -

      -
      -
      -
      -
      - AddRespondersPopup -
      -
      -
      -`; - -exports[`AddResponders should render properly in create mode 1`] = ` -
      -
      -
      -
      -
      -

      - - Participants - -

      -
      -
      -
      - -
      -
      -
      -
      -
      - AddRespondersPopup -
      -
      -
      -`; - -exports[`AddResponders should render properly in update mode 1`] = ` -
      -
      -
      -
      -
      -

      - - Participants - -

      -
      -
      -
      - -
      -
      -
      -
      -
      - AddRespondersPopup -
      -
      -
      -`; - -exports[`AddResponders should render selected team and users properly 1`] = ` -
      -
      -
      -
      -
      -

      - - Participants - -

      -
      -
      -
      - -
      -
      -
      -
        -
      • -
        -
        -
        -
        -
        - -
        -
        -
        - - my test team - -
        -
        -
        -
        -
        -
        -
      • -
      • -
        -
        -
        -
        -
        - -
        -
        -
        - - my test user3 - -
        -
        -
        -
        -
        -
        -
        - - -
        -
        -
        - Select... -
        - -
        -
        -
        -
        -
        -
        -
        -
        -
        -
        -
      • -
      • -
        -
        -
        -
        -
        - -
        -
        -
        - - my test user - -
        -
        -
        -
        -
        -
        -
        - - -
        -
        -
        - Select... -
        - -
        -
        -
        -
        -
        -
        -
        -
        -
        -
        -
      • -
      • -
        -
        -
        -
        -
        - -
        -
        -
        - - my test user2 - -
        -
        -
        -
        -
        -
        -
        - - -
        -
        -
        - Select... -
        - -
        -
        -
        -
        -
        -
        -
        -
        -
        -
        -
      • -
        -
        -
        -
        -
        -
        - - - - -
        -
        - Learn more -
        -
        -
        - -
        - about Default vs Important user personal notification settings - - -
        -
        -
        -
      -
      -
      - AddRespondersPopup -
      -
      -
      -`; diff --git a/grafana-plugin/src/containers/AddResponders/parts/AddRespondersPopup/AddRespondersPopup.test.tsx b/grafana-plugin/src/containers/AddResponders/parts/AddRespondersPopup/AddRespondersPopup.test.tsx deleted file mode 100644 index 850556d829..0000000000 --- a/grafana-plugin/src/containers/AddResponders/parts/AddRespondersPopup/AddRespondersPopup.test.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import React from 'react'; - -import { render, waitFor } from '@testing-library/react'; -import { Provider } from 'mobx-react'; - -import { UserHelper } from 'models/user/user.helpers'; - -import { AddRespondersPopup } from './AddRespondersPopup'; - -describe('AddRespondersPopup', () => { - const teams = [ - { - id: 1, - avatar_url: 'https://example.com', - name: 'my test team', - number_of_users_currently_oncall: 1, - }, - { - id: 2, - avatar_url: 'https://example.com', - name: 'my test team 2', - number_of_users_currently_oncall: 0, - }, - ]; - - test('it shows a loading message initially', async () => { - const mockStoreValue = { - directPagingStore: { - selectedTeamResponder: null, - }, - grafanaTeamStore: { - getSearchResult: jest.fn().mockReturnValue(teams), - updateItems: jest.fn(), - }, - }; - - UserHelper.search = jest.fn().mockReturnValue({ results: [] }); - - await waitFor(() => { - const component = render( - - - - ); - - expect(component.container).toMatchSnapshot(); - }); - }); -}); diff --git a/grafana-plugin/src/containers/AddResponders/parts/AddRespondersPopup/AddRespondersPopup.tsx b/grafana-plugin/src/containers/AddResponders/parts/AddRespondersPopup/AddRespondersPopup.tsx index 8f998bc9e5..da2fb3d963 100644 --- a/grafana-plugin/src/containers/AddResponders/parts/AddRespondersPopup/AddRespondersPopup.tsx +++ b/grafana-plugin/src/containers/AddResponders/parts/AddRespondersPopup/AddRespondersPopup.tsx @@ -1,6 +1,6 @@ import React, { useState, useCallback, useEffect, useRef, FC } from 'react'; -import { Alert, HorizontalGroup, Icon, Input, LoadingPlaceholder, RadioButtonGroup } from '@grafana/ui'; +import { Alert, Icon, Input, LoadingPlaceholder, RadioButtonGroup, Stack } from '@grafana/ui'; import cn from 'classnames/bind'; import { observer } from 'mobx-react'; import { ColumnsType } from 'rc-table/lib/interface'; @@ -12,6 +12,7 @@ import { GrafanaTeam } from 'models/grafana_team/grafana_team.types'; import { UserHelper } from 'models/user/user.helpers'; import { ApiSchemas } from 'network/oncall-api/api.types'; import { useStore } from 'state/useStore'; +import { StackSize } from 'utils/consts'; import { useDebouncedCallback, useOnClickOutside } from 'utils/hooks'; import styles from './AddRespondersPopup.module.scss'; @@ -205,17 +206,17 @@ export const AddRespondersPopup = observer( return (
      addTeamResponder(team)} className={cx('responder-item')}> - - + + {name} - + {number_of_users_currently_oncall > 0 && ( {number_of_users_currently_oncall} user{number_of_users_currently_oncall > 1 ? 's' : ''} on-call )} - +
      ); }, @@ -233,20 +234,20 @@ export const AddRespondersPopup = observer( return (
      (disabled ? undefined : onClickUser(user))} className={cx('responder-item')}> - - + + {name || username} - + {/* TODO: we should add an elippsis and/or tooltip in the event that the user has a ton of teams */} {teams?.length > 0 && ( {teams.map(({ name }) => name).join(', ')} )} - +
      ); }, @@ -329,10 +330,10 @@ export const AddRespondersPopup = observer( rel="noreferrer" > - + Learn more - +
      diff --git a/grafana-plugin/src/containers/AddResponders/parts/AddRespondersPopup/__snapshots__/AddRespondersPopup.test.tsx.snap b/grafana-plugin/src/containers/AddResponders/parts/AddRespondersPopup/__snapshots__/AddRespondersPopup.test.tsx.snap deleted file mode 100644 index e27f7058e7..0000000000 --- a/grafana-plugin/src/containers/AddResponders/parts/AddRespondersPopup/__snapshots__/AddRespondersPopup.test.tsx.snap +++ /dev/null @@ -1,82 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`AddRespondersPopup it shows a loading message initially 1`] = ` -
      -
      -
      -
      - -
      -
      -
      -
      -
      - - -
      -
      - - -
      -
      -
      - Loading... - -
      -
      -
      -
      -`; diff --git a/grafana-plugin/src/containers/AddResponders/parts/NotificationPoliciesSelect/NotificationPoliciesSelect.test.tsx b/grafana-plugin/src/containers/AddResponders/parts/NotificationPoliciesSelect/NotificationPoliciesSelect.test.tsx deleted file mode 100644 index 914b4bffe3..0000000000 --- a/grafana-plugin/src/containers/AddResponders/parts/NotificationPoliciesSelect/NotificationPoliciesSelect.test.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; - -import { render } from '@testing-library/react'; - -import { NotificationPoliciesSelect } from './NotificationPoliciesSelect'; - -describe('NotificationPoliciesSelect', () => { - test('it renders properly', () => { - const component = render( {}} />); - expect(component.container).toMatchSnapshot(); - }); - - test('disabled state', async () => { - const component = render( {}} />); - expect(component.container).toMatchSnapshot(); - }); -}); diff --git a/grafana-plugin/src/containers/AddResponders/parts/NotificationPoliciesSelect/__snapshots__/NotificationPoliciesSelect.test.tsx.snap b/grafana-plugin/src/containers/AddResponders/parts/NotificationPoliciesSelect/__snapshots__/NotificationPoliciesSelect.test.tsx.snap deleted file mode 100644 index bea4a690a5..0000000000 --- a/grafana-plugin/src/containers/AddResponders/parts/NotificationPoliciesSelect/__snapshots__/NotificationPoliciesSelect.test.tsx.snap +++ /dev/null @@ -1,100 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`NotificationPoliciesSelect disabled state 1`] = ` -
      -
      - - -
      -
      -
      - Default -
      - -
      -
      -
      -
      -
      -`; - -exports[`NotificationPoliciesSelect it renders properly 1`] = ` -
      -
      - - -
      -
      -
      - Default -
      - -
      -
      -
      -
      -
      -`; diff --git a/grafana-plugin/src/containers/AddResponders/parts/TeamResponder/TeamResponder.test.tsx b/grafana-plugin/src/containers/AddResponders/parts/TeamResponder/TeamResponder.test.tsx index 97d95d39f5..52c6660c70 100644 --- a/grafana-plugin/src/containers/AddResponders/parts/TeamResponder/TeamResponder.test.tsx +++ b/grafana-plugin/src/containers/AddResponders/parts/TeamResponder/TeamResponder.test.tsx @@ -13,11 +13,6 @@ describe('TeamResponder', () => { name: 'my test team', } as GrafanaTeam; - test('it renders data properly', () => { - const component = render( {}} />); - expect(component.container).toMatchSnapshot(); - }); - test('it calls the delete callback', async () => { const handleDelete = jest.fn(); diff --git a/grafana-plugin/src/containers/AddResponders/parts/TeamResponder/TeamResponder.tsx b/grafana-plugin/src/containers/AddResponders/parts/TeamResponder/TeamResponder.tsx index 8b88612b12..6ac459fe5c 100644 --- a/grafana-plugin/src/containers/AddResponders/parts/TeamResponder/TeamResponder.tsx +++ b/grafana-plugin/src/containers/AddResponders/parts/TeamResponder/TeamResponder.tsx @@ -1,6 +1,6 @@ import React, { FC } from 'react'; -import { HorizontalGroup, IconButton, useStyles2 } from '@grafana/ui'; +import { IconButton, Stack, useStyles2 } from '@grafana/ui'; import { Avatar } from 'components/Avatar/Avatar'; import { Text } from 'components/Text/Text'; @@ -17,20 +17,20 @@ export const TeamResponder: FC = ({ team: { avatar_url, name }, handleDel return (
    • - - + +
      {name} -
      + -
      +
    • ); }; diff --git a/grafana-plugin/src/containers/AddResponders/parts/TeamResponder/__snapshots__/TeamResponder.test.tsx.snap b/grafana-plugin/src/containers/AddResponders/parts/TeamResponder/__snapshots__/TeamResponder.test.tsx.snap deleted file mode 100644 index 9ba20fb8fb..0000000000 --- a/grafana-plugin/src/containers/AddResponders/parts/TeamResponder/__snapshots__/TeamResponder.test.tsx.snap +++ /dev/null @@ -1,55 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`TeamResponder it renders data properly 1`] = ` -
      -
    • -
      -
      -
      -
      -
      - -
      -
      -
      - - my test team - -
      -
      -
      -
      -
      -
      -
    • -
      -`; diff --git a/grafana-plugin/src/containers/AddResponders/parts/UserResponder/UserResponder.test.tsx b/grafana-plugin/src/containers/AddResponders/parts/UserResponder/UserResponder.test.tsx index a089df4d0f..9b756eba00 100644 --- a/grafana-plugin/src/containers/AddResponders/parts/UserResponder/UserResponder.test.tsx +++ b/grafana-plugin/src/containers/AddResponders/parts/UserResponder/UserResponder.test.tsx @@ -13,13 +13,6 @@ describe('UserResponder', () => { username: 'johnsmith', } as ApiSchemas['UserIsCurrentlyOnCall']; - test('it renders data properly', () => { - const component = render( - {}} handleDelete={() => {}} /> - ); - expect(component.container).toMatchSnapshot(); - }); - test('it calls the delete callback', async () => { const handleDelete = jest.fn(); diff --git a/grafana-plugin/src/containers/AddResponders/parts/UserResponder/UserResponder.tsx b/grafana-plugin/src/containers/AddResponders/parts/UserResponder/UserResponder.tsx index 3b266698b1..d6b36612ca 100644 --- a/grafana-plugin/src/containers/AddResponders/parts/UserResponder/UserResponder.tsx +++ b/grafana-plugin/src/containers/AddResponders/parts/UserResponder/UserResponder.tsx @@ -2,7 +2,7 @@ import React, { FC } from 'react'; import { cx } from '@emotion/css'; import { SelectableValue } from '@grafana/data'; -import { ActionMeta, HorizontalGroup, IconButton, useStyles2 } from '@grafana/ui'; +import { ActionMeta, IconButton, Stack, useStyles2 } from '@grafana/ui'; import { Avatar } from 'components/Avatar/Avatar'; import { Text } from 'components/Text/Text'; @@ -27,14 +27,14 @@ export const UserResponder: FC = ({ return (
    • - - + +
      {username} -
      - + + = ({ name="trash-alt" onClick={handleDelete} /> - -
      + +
    • ); }; diff --git a/grafana-plugin/src/containers/AddResponders/parts/UserResponder/__snapshots__/UserResponder.test.tsx.snap b/grafana-plugin/src/containers/AddResponders/parts/UserResponder/__snapshots__/UserResponder.test.tsx.snap deleted file mode 100644 index bc9fdd7334..0000000000 --- a/grafana-plugin/src/containers/AddResponders/parts/UserResponder/__snapshots__/UserResponder.test.tsx.snap +++ /dev/null @@ -1,112 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`UserResponder it renders data properly 1`] = ` -
      -
    • -
      -
      -
      -
      -
      - -
      -
      -
      - - johnsmith - -
      -
      -
      -
      -
      -
      -
      - - -
      -
      -
      - Important -
      - -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
    • -
      -`; diff --git a/grafana-plugin/src/containers/AlertRules/AlertRules.tsx b/grafana-plugin/src/containers/AlertRules/AlertRules.tsx index 82c2941cc6..517d49e852 100644 --- a/grafana-plugin/src/containers/AlertRules/AlertRules.tsx +++ b/grafana-plugin/src/containers/AlertRules/AlertRules.tsx @@ -1,6 +1,6 @@ import React, { useEffect } from 'react'; -import { VerticalGroup, useTheme2 } from '@grafana/ui'; +import { Stack, useTheme2 } from '@grafana/ui'; import { Timeline } from 'components/Timeline/Timeline'; import { MSTeamsConnector } from 'containers/AlertRules/parts/connectors/MSTeamsConnector'; @@ -38,11 +38,11 @@ export const ChatOpsConnectors = (props: ChatOpsConnectorsProps) => { return ( - + {isSlackInstalled && } {isTelegramInstalled && } {isMSTeamsInstalled && } - + ); }; diff --git a/grafana-plugin/src/containers/AlertRules/parts/connectors/MSTeamsConnector.tsx b/grafana-plugin/src/containers/AlertRules/parts/connectors/MSTeamsConnector.tsx index 138c3d1f68..c4ff554807 100644 --- a/grafana-plugin/src/containers/AlertRules/parts/connectors/MSTeamsConnector.tsx +++ b/grafana-plugin/src/containers/AlertRules/parts/connectors/MSTeamsConnector.tsx @@ -1,6 +1,6 @@ import React, { useCallback } from 'react'; -import { HorizontalGroup, InlineSwitch } from '@grafana/ui'; +import { InlineSwitch, Stack } from '@grafana/ui'; import cn from 'classnames/bind'; import { observer } from 'mobx-react'; @@ -10,6 +10,7 @@ import { ChannelFilter } from 'models/channel_filter/channel_filter.types'; import { MSTeamsChannel } from 'models/msteams_channel/msteams_channel.types'; import { useStore } from 'state/useStore'; import { UserActions } from 'utils/authorization/authorization'; +import { StackSize } from 'utils/consts'; import styles from 'containers/AlertRules/parts/connectors/Connectors.module.css'; @@ -48,7 +49,7 @@ export const MSTeamsConnector = observer((props: MSTeamsConnectorProps) => { return (
      - +
      { onChange={handleMSTeamsChannelChange} /> - +
      ); }); diff --git a/grafana-plugin/src/containers/AlertRules/parts/connectors/SlackConnector.tsx b/grafana-plugin/src/containers/AlertRules/parts/connectors/SlackConnector.tsx index ba7abdeb81..f887cb183b 100644 --- a/grafana-plugin/src/containers/AlertRules/parts/connectors/SlackConnector.tsx +++ b/grafana-plugin/src/containers/AlertRules/parts/connectors/SlackConnector.tsx @@ -1,6 +1,6 @@ import React, { useCallback } from 'react'; -import { HorizontalGroup, InlineSwitch } from '@grafana/ui'; +import { InlineSwitch, Stack } from '@grafana/ui'; import cn from 'classnames/bind'; import { observer } from 'mobx-react'; @@ -11,6 +11,7 @@ import { PRIVATE_CHANNEL_NAME } from 'models/slack_channel/slack_channel.config' import { SlackChannel } from 'models/slack_channel/slack_channel.types'; import { useStore } from 'state/useStore'; import { UserActions } from 'utils/authorization/authorization'; +import { StackSize } from 'utils/consts'; import styles from './Connectors.module.css'; @@ -45,7 +46,7 @@ export const SlackConnector = observer((props: SlackConnectorProps) => { return (
      - +
      { nullItemName={PRIVATE_CHANNEL_NAME} /> - +
      ); diff --git a/grafana-plugin/src/containers/AlertRules/parts/connectors/TelegramConnector.tsx b/grafana-plugin/src/containers/AlertRules/parts/connectors/TelegramConnector.tsx index 1d5db0dbad..b53cdba288 100644 --- a/grafana-plugin/src/containers/AlertRules/parts/connectors/TelegramConnector.tsx +++ b/grafana-plugin/src/containers/AlertRules/parts/connectors/TelegramConnector.tsx @@ -1,6 +1,6 @@ import React, { useCallback } from 'react'; -import { HorizontalGroup, InlineSwitch } from '@grafana/ui'; +import { InlineSwitch, Stack } from '@grafana/ui'; import cn from 'classnames/bind'; import { observer } from 'mobx-react'; @@ -10,6 +10,7 @@ import { ChannelFilter } from 'models/channel_filter/channel_filter.types'; import { TelegramChannel } from 'models/telegram_channel/telegram_channel.types'; import { useStore } from 'state/useStore'; import { UserActions } from 'utils/authorization/authorization'; +import { StackSize } from 'utils/consts'; import styles from './Connectors.module.css'; @@ -40,7 +41,7 @@ export const TelegramConnector = observer(({ channelFilterId }: TelegramConnecto return (
      - +
      - +
      ); }); diff --git a/grafana-plugin/src/containers/ApiTokenSettings/ApiTokenForm.tsx b/grafana-plugin/src/containers/ApiTokenSettings/ApiTokenForm.tsx index e6b645be2d..c5d32a7d85 100644 --- a/grafana-plugin/src/containers/ApiTokenSettings/ApiTokenForm.tsx +++ b/grafana-plugin/src/containers/ApiTokenSettings/ApiTokenForm.tsx @@ -1,6 +1,6 @@ import React, { HTMLAttributes, useState } from 'react'; -import { Button, Field, HorizontalGroup, Input, Label, Modal, VerticalGroup } from '@grafana/ui'; +import { Button, Field, Input, Label, Modal, Stack } from '@grafana/ui'; import cn from 'classnames/bind'; import { get } from 'lodash-es'; import { observer } from 'mobx-react'; @@ -48,7 +48,7 @@ export const ApiTokenForm = observer((props: TokenCreationModalProps) => {
      - +
      {renderTokenInput()} @@ -57,7 +57,7 @@ export const ApiTokenForm = observer((props: TokenCreationModalProps) => { {renderCurlExample()} - + @@ -67,8 +67,8 @@ export const ApiTokenForm = observer((props: TokenCreationModalProps) => { Create Token - - + + @@ -117,12 +117,12 @@ export const ApiTokenForm = observer((props: TokenCreationModalProps) => { return null; } return ( - + {getCurlExample(token, store.pluginStore.apiUrlFromStatus)} - + ); } diff --git a/grafana-plugin/src/containers/ApiTokenSettings/ApiTokenSettings.tsx b/grafana-plugin/src/containers/ApiTokenSettings/ApiTokenSettings.tsx index f3484de1d7..e2dbd9f325 100644 --- a/grafana-plugin/src/containers/ApiTokenSettings/ApiTokenSettings.tsx +++ b/grafana-plugin/src/containers/ApiTokenSettings/ApiTokenSettings.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { Button, HorizontalGroup } from '@grafana/ui'; +import { Button, Stack } from '@grafana/ui'; import cn from 'classnames/bind'; import { observer } from 'mobx-react'; import moment from 'moment-timezone'; @@ -82,9 +82,9 @@ class _ApiTokenSettings extends React.Component { (
      - + API Tokens - + - + ); }); diff --git a/grafana-plugin/src/containers/ColumnsSelectorWrapper/ColumnsModal.tsx b/grafana-plugin/src/containers/ColumnsSelectorWrapper/ColumnsModal.tsx index dead50d3c4..25e4809c9c 100644 --- a/grafana-plugin/src/containers/ColumnsSelectorWrapper/ColumnsModal.tsx +++ b/grafana-plugin/src/containers/ColumnsSelectorWrapper/ColumnsModal.tsx @@ -1,17 +1,7 @@ import React, { useMemo, useState } from 'react'; import { LabelTag } from '@grafana/labels'; -import { - Button, - Checkbox, - HorizontalGroup, - IconButton, - Input, - LoadingPlaceholder, - Modal, - VerticalGroup, - useStyles2, -} from '@grafana/ui'; +import { Button, Checkbox, IconButton, Input, LoadingPlaceholder, Modal, Stack, useStyles2 } from '@grafana/ui'; import cn from 'classnames/bind'; import { observer } from 'mobx-react'; @@ -26,7 +16,7 @@ import { ApiSchemas } from 'network/oncall-api/api.types'; import { components } from 'network/oncall-api/autogenerated-api.types'; import { useStore } from 'state/useStore'; import { UserActions } from 'utils/authorization/authorization'; -import { PROCESSING_REQUEST_ERROR } from 'utils/consts'; +import { PROCESSING_REQUEST_ERROR, StackSize } from 'utils/consts'; import { WrapWithGlobalNotification } from 'utils/decorators'; import { useDebouncedCallback, useIsLoading } from 'utils/hooks'; import { pluralize } from 'utils/utils'; @@ -68,9 +58,9 @@ export const ColumnsModal: React.FC = observer( return ( - +
      - + = observer( )} {inputRef?.current?.value && searchResults.length && ( - + {searchResults.map((result, index) => ( - +
      = observer( )} )} - + ))} - + )} {inputRef?.current?.value && searchResults.length === 0 && ( 0 results for your search. )} - +
      - + @@ -149,19 +139,19 @@ export const ColumnsModal: React.FC = observer( {isLoading ? : 'Add'} - -
      +
      +
      ); function renderLabelValues(keyName: string, values: Array) { return ( - + {values.slice(0, 2).map((val) => ( ))}
      {values.length > 2 ? `+ ${values.length - 2}` : ``}
      -
      + ); } diff --git a/grafana-plugin/src/containers/ColumnsSelectorWrapper/ColumnsSelectorWrapper.tsx b/grafana-plugin/src/containers/ColumnsSelectorWrapper/ColumnsSelectorWrapper.tsx index eb346615b9..84b2d7b083 100644 --- a/grafana-plugin/src/containers/ColumnsSelectorWrapper/ColumnsSelectorWrapper.tsx +++ b/grafana-plugin/src/containers/ColumnsSelectorWrapper/ColumnsSelectorWrapper.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useRef, useState } from 'react'; -import { useStyles2, Button, HorizontalGroup, Icon, LoadingPlaceholder, Modal, VerticalGroup } from '@grafana/ui'; +import { useStyles2, Button, Icon, LoadingPlaceholder, Modal, Stack } from '@grafana/ui'; import { observer } from 'mobx-react'; import { Text } from 'components/Text/Text'; @@ -13,7 +13,7 @@ import { ActionKey } from 'models/loader/action-keys'; import { ApiSchemas } from 'network/oncall-api/api.types'; import { useStore } from 'state/useStore'; import { UserActions } from 'utils/authorization/authorization'; -import { PROCESSING_REQUEST_ERROR } from 'utils/consts'; +import { PROCESSING_REQUEST_ERROR, StackSize } from 'utils/consts'; import { WrapAutoLoadingState, WrapWithGlobalNotification } from 'utils/decorators'; import { useIsLoading } from 'utils/hooks'; @@ -68,10 +68,10 @@ export const ColumnsSelectorWrapper: React.FC = obs onDismiss={onConfirmRemovalClose} className={styles.removalModal} > - + Are you sure you want to remove column {columnToBeRemoved?.name}? - + @@ -90,8 +90,8 @@ export const ColumnsSelectorWrapper: React.FC = obs {isRemoveLoading ? : 'Remove'} - - + +
      @@ -147,10 +147,10 @@ export const ColumnsSelectorWrapper: React.FC = obs id="toggletip-button" onClick={() => setIsFloatingDisplayOpen(!isFloatingDisplayOpen)} > - + Columns - + ); } diff --git a/grafana-plugin/src/containers/EditRegexpRouteTemplateModal/EditRegexpRouteTemplateModal.tsx b/grafana-plugin/src/containers/EditRegexpRouteTemplateModal/EditRegexpRouteTemplateModal.tsx index f9f859f79a..2b3a4df21f 100644 --- a/grafana-plugin/src/containers/EditRegexpRouteTemplateModal/EditRegexpRouteTemplateModal.tsx +++ b/grafana-plugin/src/containers/EditRegexpRouteTemplateModal/EditRegexpRouteTemplateModal.tsx @@ -1,6 +1,6 @@ import React, { useState, useCallback } from 'react'; -import { HorizontalGroup, VerticalGroup, Modal, Tooltip, Icon, Button } from '@grafana/ui'; +import { Stack, Modal, Tooltip, Icon, Button } from '@grafana/ui'; import cn from 'classnames/bind'; import { debounce } from 'lodash-es'; import { observer } from 'mobx-react'; @@ -13,6 +13,7 @@ import { AlertReceiveChannelHelper } from 'models/alert_receive_channel/alert_re import { ChannelFilter } from 'models/channel_filter/channel_filter.types'; import { ApiSchemas } from 'network/oncall-api/api.types'; import { useStore } from 'state/useStore'; +import { StackSize } from 'utils/consts'; import { openErrorNotification } from 'utils/utils'; import styles from './EditRegexpRouteTemplateModal.module.css'; @@ -78,9 +79,9 @@ export const EditRegexpRouteTemplateModal = observer((props: EditRegexpRouteTemp title="Edit regular expression template" className={cx('regexp-template-editor-modal')} > - - - + + + Regular expression - +
      -
      - + + Click "Convert to Jinja2" for a rich editor with debugger and additional functionality Your template will be saved as the jinja2 template below - + {templateJinja2Body} - + @@ -118,8 +119,8 @@ export const EditRegexpRouteTemplateModal = observer((props: EditRegexpRouteTemp - -
      + + ); }); diff --git a/grafana-plugin/src/containers/EscalationChainCard/EscalationChainCard.tsx b/grafana-plugin/src/containers/EscalationChainCard/EscalationChainCard.tsx index fc003974bc..855bfcb4ec 100644 --- a/grafana-plugin/src/containers/EscalationChainCard/EscalationChainCard.tsx +++ b/grafana-plugin/src/containers/EscalationChainCard/EscalationChainCard.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { HorizontalGroup, VerticalGroup, Badge } from '@grafana/ui'; +import { Stack, Badge } from '@grafana/ui'; import cn from 'classnames/bind'; import { observer } from 'mobx-react'; @@ -8,6 +8,7 @@ import { Text } from 'components/Text/Text'; import { TeamName } from 'containers/TeamName/TeamName'; import { EscalationChain } from 'models/escalation_chain/escalation_chain.types'; import { useStore } from 'state/useStore'; +import { StackSize } from 'utils/consts'; import styles from './EscalationChainCard.module.css'; @@ -28,26 +29,31 @@ export const EscalationChainCard = observer((props: AlertReceiveChannelCardProps return (
      - - - + + + {escalationChain.name} - 0 || escalationChain.number_of_routes > 0 - ? `Modifying this escalation chain will affect ${escalationChain.number_of_integrations} integrations and ${escalationChain.number_of_routes} routes.` - : 'This escalation is not connected to any integration route, go to integrations and connect route to this escalation chain' - } - /> - - - - +
      + 0 || escalationChain.number_of_routes > 0 + ? `Modifying this escalation chain will affect ${escalationChain.number_of_integrations} integrations and ${escalationChain.number_of_routes} routes.` + : 'This escalation is not connected to any integration route, go to integrations and connect route to this escalation chain' + } + /> +
      + + +
      + +
      + +
      ); }); diff --git a/grafana-plugin/src/containers/EscalationChainForm/EscalationChainForm.tsx b/grafana-plugin/src/containers/EscalationChainForm/EscalationChainForm.tsx index a2fb59d4da..402eba69a3 100644 --- a/grafana-plugin/src/containers/EscalationChainForm/EscalationChainForm.tsx +++ b/grafana-plugin/src/containers/EscalationChainForm/EscalationChainForm.tsx @@ -1,6 +1,6 @@ import React, { FC } from 'react'; -import { Button, Field, HorizontalGroup, Input, Modal } from '@grafana/ui'; +import { Button, Field, Input, Modal, Stack } from '@grafana/ui'; import cn from 'classnames/bind'; import { observer } from 'mobx-react'; import { Controller, FormProvider, useForm } from 'react-hook-form'; @@ -108,14 +108,14 @@ export const EscalationChainForm: FC = observer((props )} /> - + - +
      diff --git a/grafana-plugin/src/containers/GSelect/GSelect.tsx b/grafana-plugin/src/containers/GSelect/GSelect.tsx index ba0bcea8fc..fe18d5dacd 100644 --- a/grafana-plugin/src/containers/GSelect/GSelect.tsx +++ b/grafana-plugin/src/containers/GSelect/GSelect.tsx @@ -43,6 +43,7 @@ interface GSelectProps { openMenuOnFocus?: boolean; width?: number | 'auto'; icon?: string; + dataTestId?: string; } export const GSelect = observer((props: GSelectProps) => { @@ -72,6 +73,7 @@ export const GSelect = observer((props: GSelectProps) => { fetchItemFn, getSearchResult, parseDisplayName, + dataTestId = null, } = props; const onChangeCallback = useCallback( @@ -151,7 +153,7 @@ export const GSelect = observer((props: GSelectProps) => { const Tag = isMulti ? AsyncMultiSelect : AsyncSelect; return ( -
      +
      - + + + ); } diff --git a/grafana-plugin/src/containers/IntegrationContainers/CollapsedIntegrationRouteDisplay/CollapsedIntegrationRouteDisplay.tsx b/grafana-plugin/src/containers/IntegrationContainers/CollapsedIntegrationRouteDisplay/CollapsedIntegrationRouteDisplay.tsx index 63e402ed1e..6908310617 100644 --- a/grafana-plugin/src/containers/IntegrationContainers/CollapsedIntegrationRouteDisplay/CollapsedIntegrationRouteDisplay.tsx +++ b/grafana-plugin/src/containers/IntegrationContainers/CollapsedIntegrationRouteDisplay/CollapsedIntegrationRouteDisplay.tsx @@ -1,6 +1,6 @@ import React, { useMemo, useState } from 'react'; -import { ConfirmModal, HorizontalGroup, Icon, IconName } from '@grafana/ui'; +import { ConfirmModal, Icon, IconName, Stack } from '@grafana/ui'; import cn from 'classnames/bind'; import { observer } from 'mobx-react'; @@ -15,6 +15,7 @@ import { ApiSchemas } from 'network/oncall-api/api.types'; import { CommonIntegrationHelper } from 'pages/integration/CommonIntegration.helper'; import { IntegrationHelper } from 'pages/integration/Integration.helper'; import { useStore } from 'state/useStore'; +import { StackSize } from 'utils/consts'; const cx = cn.bind(styles); @@ -95,7 +96,7 @@ export const CollapsedIntegrationRouteDisplay: React.FC {chatOpsAvailableChannels.length > 0 && (
      - + Publish to ChatOps {chatOpsAvailableChannels.map( @@ -109,7 +110,7 @@ export const CollapsedIntegrationRouteDisplay: React.FC ) )} - +
      )} diff --git a/grafana-plugin/src/containers/IntegrationContainers/ExpandedIntegrationRouteDisplay/ExpandedIntegrationRouteDisplay.tsx b/grafana-plugin/src/containers/IntegrationContainers/ExpandedIntegrationRouteDisplay/ExpandedIntegrationRouteDisplay.tsx index 504b00a76d..83140b9e0e 100644 --- a/grafana-plugin/src/containers/IntegrationContainers/ExpandedIntegrationRouteDisplay/ExpandedIntegrationRouteDisplay.tsx +++ b/grafana-plugin/src/containers/IntegrationContainers/ExpandedIntegrationRouteDisplay/ExpandedIntegrationRouteDisplay.tsx @@ -3,8 +3,7 @@ import React, { useEffect, useReducer, useState } from 'react'; import { SelectableValue } from '@grafana/data'; import { Button, - HorizontalGroup, - VerticalGroup, + Stack, Icon, Tooltip, ConfirmModal, @@ -44,6 +43,7 @@ import { MONACO_INPUT_HEIGHT_SMALL } from 'pages/integration/IntegrationCommon.c import { AppFeature } from 'state/features'; import { useStore } from 'state/useStore'; import { UserActions } from 'utils/authorization/authorization'; +import { StackSize } from 'utils/consts'; import { openNotification } from 'utils/utils'; const cx = cn.bind(styles); @@ -179,13 +179,13 @@ export const ExpandedIntegrationRouteDisplay: React.FC
      ) : ( - + {hasLabels ? 'Alerts matched by' : 'Use routing template'} - +
      - + @@ -210,14 +210,14 @@ export const ExpandedIntegrationRouteDisplay: React.FC - + - + - - + +
      handleEditRoutingTemplate(channelFilter, channelFilterId)} /> - + - + - + )}
      ), @@ -261,12 +261,12 @@ export const ExpandedIntegrationRouteDisplay: React.FC (
      - + Publish to ChatOps - +
      ), }, @@ -279,13 +279,13 @@ export const ExpandedIntegrationRouteDisplay: React.FC (
      - + Trigger escalation chain
      - + onInheritanceChange(label.key.id)} /> - + ))}
    - + ) : ( - + There are no labels to inherit yet Add labels to the integration - + )} - + - - + + Allows for the extraction and modification of multiple labels from the alert payload using a single template. Supports not only dynamic values but also dynamic keys. The Jinja template must result in @@ -172,7 +162,7 @@ export const IntegrationLabelsForm = observer((props: IntegrationLabelsFormProps setShowTemplateEditor(true); }} /> - + - +
    - + - +
    - + {customLabelIndexToShowTemplateEditor !== undefined && ( { }; return ( - + Dynamic & Static labels Dynamic: label values are extracted from the alert payload using Jinja. Keys remain static. @@ -376,6 +366,6 @@ const CustomLabels = (props: CustomLabelsProps) => { Add label - + ); }; diff --git a/grafana-plugin/src/containers/IntegrationTemplate/IntegrationTemplate.tsx b/grafana-plugin/src/containers/IntegrationTemplate/IntegrationTemplate.tsx index a3adcd8cd5..6481b64efc 100644 --- a/grafana-plugin/src/containers/IntegrationTemplate/IntegrationTemplate.tsx +++ b/grafana-plugin/src/containers/IntegrationTemplate/IntegrationTemplate.tsx @@ -1,6 +1,6 @@ import React, { useCallback, useState, useEffect } from 'react'; -import { Button, HorizontalGroup, Drawer, VerticalGroup } from '@grafana/ui'; +import { Button, Drawer, Stack } from '@grafana/ui'; import cn from 'classnames/bind'; import { debounce } from 'lodash-es'; import { observer } from 'mobx-react'; @@ -165,13 +165,13 @@ export const IntegrationTemplate = observer((props: IntegrationTemplateProps) => - - + + Edit {template.displayName} template {template.description && {template.description}} - + - + - - + +
    } onClose={onHide} @@ -231,13 +231,13 @@ export const IntegrationTemplate = observer((props: IntegrationTemplateProps) => <>
    - + Template editor - +
    = observer((props }; return ( - + {!personalSettings && Connect MS Teams workspace} {showInfoBox && ( - +
    You can manage alert groups in your Microsoft Teams workspace.
    {personalSettings ? ( - + This setup is for direct profile connection with bot.
    To manage alert groups in Team channel, setup{' '} Team ChatOps -
    +
    ) : ( - + This setup is for Team channel connection with bot.
    To manage alert groups in Direct Messages and verify users who are allowed to operate with MS Teams, setup personal MS Teams connection -
    +
    )} -
    + )} @@ -126,6 +127,6 @@ export const MSTeamsInstructions: FC = observer((props
    )} - + ); }); diff --git a/grafana-plugin/src/containers/MaintenanceForm/MaintenanceForm.tsx b/grafana-plugin/src/containers/MaintenanceForm/MaintenanceForm.tsx index d8d30084f2..f1f367baec 100644 --- a/grafana-plugin/src/containers/MaintenanceForm/MaintenanceForm.tsx +++ b/grafana-plugin/src/containers/MaintenanceForm/MaintenanceForm.tsx @@ -1,7 +1,7 @@ import React, { useCallback } from 'react'; import { SelectableValue } from '@grafana/data'; -import { Button, Drawer, Field, HorizontalGroup, Select, VerticalGroup, useStyles2 } from '@grafana/ui'; +import { Button, Drawer, Field, Select, Stack, useStyles2 } from '@grafana/ui'; import cn from 'classnames/bind'; import { observer } from 'mobx-react'; import Emoji from 'react-emoji-render'; @@ -74,7 +74,7 @@ export const MaintenanceForm = observer((props: MaintenanceFormProps) => { return (
    - + Start maintenance mode when performing scheduled maintenance or updates on the infrastructure, which may trigger false alarms. @@ -182,7 +182,7 @@ export const MaintenanceForm = observer((props: MaintenanceFormProps) => { )} /> - + @@ -191,10 +191,10 @@ export const MaintenanceForm = observer((props: MaintenanceFormProps) => { Start - + - +
    ); diff --git a/grafana-plugin/src/containers/MobileAppConnection/MobileAppConnection.test.tsx b/grafana-plugin/src/containers/MobileAppConnection/MobileAppConnection.test.tsx index 03cb1746ee..932cc87658 100644 --- a/grafana-plugin/src/containers/MobileAppConnection/MobileAppConnection.test.tsx +++ b/grafana-plugin/src/containers/MobileAppConnection/MobileAppConnection.test.tsx @@ -2,7 +2,6 @@ import React from 'react'; import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { MemoryRouter } from 'react-router-dom-v5-compat'; import { UserHelper } from 'models/user/user.helpers'; import { ApiSchemas } from 'network/oncall-api/api.types'; @@ -64,8 +63,7 @@ describe('MobileAppConnection', () => { }); test('it shows a loading message if it is currently fetching the QR code', async () => { - const component = render(); - expect(component.container).toMatchSnapshot(); + render(); await waitFor(() => { expect(UserHelper.fetchBackendConfirmationCode).toHaveBeenCalledTimes(1); @@ -75,20 +73,17 @@ describe('MobileAppConnection', () => { test('it shows an error message if there was an error fetching the QR code', async () => { UserHelper.fetchBackendConfirmationCode = jest.fn().mockRejectedValueOnce('dfd'); - const component = render(); + render(); await screen.findByText(/.*error fetching your QR code.*/); await waitFor(() => { - expect(component.container).toMatchSnapshot(); - expect(UserHelper.fetchBackendConfirmationCode).toHaveBeenCalledTimes(1); expect(UserHelper.fetchBackendConfirmationCode).toHaveBeenCalledWith(USER_PK, BACKEND); }); }); test("it shows a QR code if the app isn't already connected", async () => { - const component = render(); - expect(component.container).toMatchSnapshot(); + render(); await waitFor(() => { expect(UserHelper.fetchBackendConfirmationCode).toHaveBeenCalledTimes(1); @@ -113,8 +108,6 @@ describe('MobileAppConnection', () => { // click the confirm button within the modal, which actually triggers the callback await userEvent.click(screen.getByText('Remove')); - // expect(component.container).toMatchSnapshot(); - await waitFor(() => { expect(UserHelper.fetchBackendConfirmationCode).toHaveBeenCalledTimes(1); expect(UserHelper.fetchBackendConfirmationCode).toHaveBeenCalledWith(USER_PK, BACKEND); @@ -132,7 +125,7 @@ describe('MobileAppConnection', () => { true ); - const component = render(); + render(); const button = await screen.findByRole('button'); // click the disconnect button, which opens the modal @@ -143,8 +136,6 @@ describe('MobileAppConnection', () => { // wait for loading state await screen.findByText(/.*Loading.*/); - expect(component.container).toMatchSnapshot(); - await waitFor(() => { expect(UserHelper.fetchBackendConfirmationCode).toHaveBeenCalledTimes(1); expect(UserHelper.fetchBackendConfirmationCode).toHaveBeenCalledWith(USER_PK, BACKEND); @@ -162,7 +153,7 @@ describe('MobileAppConnection', () => { true ); - const component = render(); + render(); const button = await screen.findByTestId('test__disconnect'); // click the disconnect button, which opens the modal @@ -172,8 +163,6 @@ describe('MobileAppConnection', () => { await screen.findByText(/.*error disconnecting your mobile app.*/); - expect(component.container).toMatchSnapshot(); - await waitFor(() => { expect(UserHelper.fetchBackendConfirmationCode).toHaveBeenCalledTimes(0); @@ -223,16 +212,4 @@ describe('MobileAppConnection', () => { { timeout: 6000 } ); }); - - test('it shows a warning when cloud is not connected', async () => { - mockRootStore({}, true, false); - - // Using MemoryRouter to avoid "Invariant failed: You should not use outside a " - const component = render( - - - - ); - expect(component.container).toMatchSnapshot(); - }); }); diff --git a/grafana-plugin/src/containers/MobileAppConnection/MobileAppConnection.tsx b/grafana-plugin/src/containers/MobileAppConnection/MobileAppConnection.tsx index 27b9c704a5..1ab887b21e 100644 --- a/grafana-plugin/src/containers/MobileAppConnection/MobileAppConnection.tsx +++ b/grafana-plugin/src/containers/MobileAppConnection/MobileAppConnection.tsx @@ -1,6 +1,6 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'; -import { Button, HorizontalGroup, Icon, LoadingPlaceholder, VerticalGroup } from '@grafana/ui'; +import { Button, Icon, LoadingPlaceholder, Stack } from '@grafana/ui'; import cn from 'classnames/bind'; import { observer } from 'mobx-react'; @@ -16,6 +16,7 @@ import { ApiSchemas } from 'network/oncall-api/api.types'; import { AppFeature } from 'state/features'; import { RootStore, rootStore as store } from 'state/rootStore'; import { UserActions } from 'utils/authorization/authorization'; +import { StackSize } from 'utils/consts'; import { useInitializePlugin } from 'utils/hooks'; import { isMobile, openErrorNotification, openNotification, openWarningNotification } from 'utils/utils'; @@ -155,7 +156,7 @@ export const MobileAppConnection = observer(({ userPk }: Props) => { content = {errorFetchingQRCode || errorDisconnectingMobileApp}; } else if (mobileAppIsCurrentlyConnected) { content = ( - + App connected @@ -167,11 +168,11 @@ export const MobileAppConnection = observer(({ userPk }: Props) => {
    - + ); } else if (QRCodeValue) { content = ( - + Sign in via QR Code @@ -191,14 +192,14 @@ export const MobileAppConnection = observer(({ userPk }: Props) => { )} - + ); } return ( <>

    Mobile App Connection

    - +
    {QRCodeDataParsed && isMobile && ( @@ -214,7 +215,7 @@ export const MobileAppConnection = observer(({ userPk }: Props) => {
    {mobileAppIsCurrentlyConnected && isCurrentUser && !disconnectingMobileApp && (
    - + - +
    )} -
    + ); function renderConnectToCloud() { return ( - + Please connect Grafana Cloud OnCall to use the mobile app { - + ); } diff --git a/grafana-plugin/src/containers/MobileAppConnection/__snapshots__/MobileAppConnection.test.tsx.snap b/grafana-plugin/src/containers/MobileAppConnection/__snapshots__/MobileAppConnection.test.tsx.snap deleted file mode 100644 index 1e21c7f738..0000000000 --- a/grafana-plugin/src/containers/MobileAppConnection/__snapshots__/MobileAppConnection.test.tsx.snap +++ /dev/null @@ -1,635 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`MobileAppConnection it shows a QR code if the app isn't already connected 1`] = ` -
    -

    - Mobile App Connection -

    -
    -
    -
    -
    -
    - Loading... - -
    -
    -
    -
    -
    -
    - - Download - -
    -
    - - The Grafana OnCall app is available on both the App Store and Google Play Store. - -
    - -
    -
    -
    -
    -
    -
    -`; - -exports[`MobileAppConnection it shows a loading message if it is currently disconnecting 1`] = ` -
    -

    - Mobile App Connection -

    -
    -
    -
    -
    -
    - Loading... - -
    -
    -
    -
    -
    -
    - - Download - -
    -
    - - The Grafana OnCall app is available on both the App Store and Google Play Store. - -
    - -
    -
    -
    -
    -
    -
    -`; - -exports[`MobileAppConnection it shows a loading message if it is currently fetching the QR code 1`] = ` -
    -

    - Mobile App Connection -

    -
    -
    -
    -
    -
    - Loading... - -
    -
    -
    -
    -
    -
    - - Download - -
    -
    - - The Grafana OnCall app is available on both the App Store and Google Play Store. - -
    - -
    -
    -
    -
    -
    -
    -`; - -exports[`MobileAppConnection it shows a warning when cloud is not connected 1`] = ` -
    -
    -
    - - Please connect Grafana Cloud OnCall to use the mobile app - -
    - -
    -
    -`; - -exports[`MobileAppConnection it shows an error message if there was an error disconnecting the mobile app 1`] = ` -
    -

    - Mobile App Connection -

    -
    -
    -
    -
    - - There was an error disconnecting your mobile app. Please try again. - -
    -
    -
    -
    - - Download - -
    -
    - - The Grafana OnCall app is available on both the App Store and Google Play Store. - -
    - -
    -
    -
    -
    -
    -
    -`; - -exports[`MobileAppConnection it shows an error message if there was an error fetching the QR code 1`] = ` -
    -

    - Mobile App Connection -

    -
    -
    -
    -
    - - There was an error fetching your QR code. Please try again. - -
    -
    -
    -
    - - Download - -
    -
    - - The Grafana OnCall app is available on both the App Store and Google Play Store. - -
    - -
    -
    -
    -
    -
    -
    -`; diff --git a/grafana-plugin/src/containers/MobileAppConnection/parts/DisconnectButton/DisconnectButton.test.tsx b/grafana-plugin/src/containers/MobileAppConnection/parts/DisconnectButton/DisconnectButton.test.tsx index a0aadfa995..0dadea0b3a 100644 --- a/grafana-plugin/src/containers/MobileAppConnection/parts/DisconnectButton/DisconnectButton.test.tsx +++ b/grafana-plugin/src/containers/MobileAppConnection/parts/DisconnectButton/DisconnectButton.test.tsx @@ -6,11 +6,6 @@ import userEvent from '@testing-library/user-event'; import { DisconnectButton } from './DisconnectButton'; describe('DisconnectButton', () => { - test('it renders properly', () => { - const component = render( {}} />); - expect(component.container).toMatchSnapshot(); - }); - test('It calls the onClick handler when clicked', async () => { const mockedOnClick = jest.fn(); diff --git a/grafana-plugin/src/containers/MobileAppConnection/parts/DisconnectButton/__snapshots__/DisconnectButton.test.tsx.snap b/grafana-plugin/src/containers/MobileAppConnection/parts/DisconnectButton/__snapshots__/DisconnectButton.test.tsx.snap deleted file mode 100644 index e0bab5f1ad..0000000000 --- a/grafana-plugin/src/containers/MobileAppConnection/parts/DisconnectButton/__snapshots__/DisconnectButton.test.tsx.snap +++ /dev/null @@ -1,18 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`DisconnectButton it renders properly 1`] = ` -
    - -
    -`; diff --git a/grafana-plugin/src/containers/MobileAppConnection/parts/DownloadIcons/DownloadIcons.test.tsx b/grafana-plugin/src/containers/MobileAppConnection/parts/DownloadIcons/DownloadIcons.test.tsx deleted file mode 100644 index 0bfd830ae2..0000000000 --- a/grafana-plugin/src/containers/MobileAppConnection/parts/DownloadIcons/DownloadIcons.test.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; - -import { render } from '@testing-library/react'; - -import { DownloadIcons } from './DownloadIcons'; - -describe('DownloadIcons', () => { - test('it renders properly', () => { - const component = render(); - expect(component.container).toMatchSnapshot(); - }); -}); diff --git a/grafana-plugin/src/containers/MobileAppConnection/parts/DownloadIcons/DownloadIcons.tsx b/grafana-plugin/src/containers/MobileAppConnection/parts/DownloadIcons/DownloadIcons.tsx index a2fba9d455..076c63705b 100644 --- a/grafana-plugin/src/containers/MobileAppConnection/parts/DownloadIcons/DownloadIcons.tsx +++ b/grafana-plugin/src/containers/MobileAppConnection/parts/DownloadIcons/DownloadIcons.tsx @@ -1,24 +1,25 @@ import React, { FC } from 'react'; -import { VerticalGroup } from '@grafana/ui'; +import { Stack } from '@grafana/ui'; import cn from 'classnames/bind'; import AppleLogoSVG from 'assets/img/apple-logo.svg'; import PlayStoreLogoSVG from 'assets/img/play-store-logo.svg'; import { Block } from 'components/GBlock/Block'; import { Text } from 'components/Text/Text'; +import { StackSize } from 'utils/consts'; import styles from './DownloadIcons.module.scss'; const cx = cn.bind(styles); export const DownloadIcons: FC = () => ( - + Download The Grafana OnCall app is available on both the App Store and Google Play Store. - + ( - - + + ); diff --git a/grafana-plugin/src/containers/MobileAppConnection/parts/DownloadIcons/__snapshots__/DownloadIcons.test.tsx.snap b/grafana-plugin/src/containers/MobileAppConnection/parts/DownloadIcons/__snapshots__/DownloadIcons.test.tsx.snap deleted file mode 100644 index dc19303527..0000000000 --- a/grafana-plugin/src/containers/MobileAppConnection/parts/DownloadIcons/__snapshots__/DownloadIcons.test.tsx.snap +++ /dev/null @@ -1,88 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`DownloadIcons it renders properly 1`] = ` -
    -
    -
    - - Download - -
    -
    - - The Grafana OnCall app is available on both the App Store and Google Play Store. - -
    - -
    -
    -`; diff --git a/grafana-plugin/src/containers/MobileAppConnection/parts/LinkLoginButton/LinkLoginButton.test.tsx b/grafana-plugin/src/containers/MobileAppConnection/parts/LinkLoginButton/LinkLoginButton.test.tsx deleted file mode 100644 index 03c81eef71..0000000000 --- a/grafana-plugin/src/containers/MobileAppConnection/parts/LinkLoginButton/LinkLoginButton.test.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; - -import { render } from '@testing-library/react'; - -import { LinkLoginButton } from './LinkLoginButton'; - -describe('LinkLoginButton', () => { - test('it renders properly', () => { - const component = render(); - expect(component.container).toMatchSnapshot(); - }); -}); diff --git a/grafana-plugin/src/containers/MobileAppConnection/parts/LinkLoginButton/LinkLoginButton.tsx b/grafana-plugin/src/containers/MobileAppConnection/parts/LinkLoginButton/LinkLoginButton.tsx index da3089874b..a6b5cde521 100644 --- a/grafana-plugin/src/containers/MobileAppConnection/parts/LinkLoginButton/LinkLoginButton.tsx +++ b/grafana-plugin/src/containers/MobileAppConnection/parts/LinkLoginButton/LinkLoginButton.tsx @@ -1,8 +1,9 @@ import React, { FC } from 'react'; -import { Button, VerticalGroup } from '@grafana/ui'; +import { Button, Stack } from '@grafana/ui'; import { Text } from 'components/Text/Text'; +import { StackSize } from 'utils/consts'; type Props = { baseUrl: string; @@ -14,7 +15,7 @@ export const LinkLoginButton: FC = (props: Props) => { const mobileDeepLink = `grafana://mobile/login/link-login?oncall_api_url=${baseUrl}&token=${token}`; return ( - + Sign in via deeplink @@ -27,6 +28,6 @@ export const LinkLoginButton: FC = (props: Props) => { > Connect Mobile App - + ); }; diff --git a/grafana-plugin/src/containers/MobileAppConnection/parts/LinkLoginButton/__snapshots__/LinkLoginButton.test.tsx.snap b/grafana-plugin/src/containers/MobileAppConnection/parts/LinkLoginButton/__snapshots__/LinkLoginButton.test.tsx.snap deleted file mode 100644 index da0987239f..0000000000 --- a/grafana-plugin/src/containers/MobileAppConnection/parts/LinkLoginButton/__snapshots__/LinkLoginButton.test.tsx.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`LinkLoginButton it renders properly 1`] = ` -
    -
    -
    - - Sign in via deeplink - -
    -
    - - Make sure to have the app installed - -
    -
    - -
    -
    -
    -`; diff --git a/grafana-plugin/src/containers/MobileAppConnection/parts/QRCode/QRCode.test.tsx b/grafana-plugin/src/containers/MobileAppConnection/parts/QRCode/QRCode.test.tsx deleted file mode 100644 index 2581a2f912..0000000000 --- a/grafana-plugin/src/containers/MobileAppConnection/parts/QRCode/QRCode.test.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; - -import { render } from '@testing-library/react'; - -import { QRCode } from './QRCode'; - -describe('QRCode', () => { - test('it renders properly', () => { - const component = render(); - expect(component.container).toMatchSnapshot(); - }); -}); diff --git a/grafana-plugin/src/containers/MobileAppConnection/parts/QRCode/__snapshots__/QRCode.test.tsx.snap b/grafana-plugin/src/containers/MobileAppConnection/parts/QRCode/__snapshots__/QRCode.test.tsx.snap deleted file mode 100644 index f902c93d4e..0000000000 --- a/grafana-plugin/src/containers/MobileAppConnection/parts/QRCode/__snapshots__/QRCode.test.tsx.snap +++ /dev/null @@ -1,26 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`QRCode it renders properly 1`] = ` -
    -
    - - - - -
    -
    -`; diff --git a/grafana-plugin/src/containers/OutgoingWebhookForm/OutgoingWebhookForm.tsx b/grafana-plugin/src/containers/OutgoingWebhookForm/OutgoingWebhookForm.tsx index 5413f640af..7de7a09d2e 100644 --- a/grafana-plugin/src/containers/OutgoingWebhookForm/OutgoingWebhookForm.tsx +++ b/grafana-plugin/src/containers/OutgoingWebhookForm/OutgoingWebhookForm.tsx @@ -1,16 +1,6 @@ import React, { ChangeEvent, useCallback, useEffect, useMemo, useState } from 'react'; -import { - Button, - ConfirmModal, - ConfirmModalProps, - Drawer, - HorizontalGroup, - Input, - Tab, - TabsBar, - VerticalGroup, -} from '@grafana/ui'; +import { Button, ConfirmModal, ConfirmModalProps, Drawer, Input, Tab, TabsBar, Stack } from '@grafana/ui'; import cn from 'classnames/bind'; import { observer } from 'mobx-react'; import { FormProvider, useForm, useFormContext } from 'react-hook-form'; @@ -212,7 +202,7 @@ const Presets = (props: PresetsProps) => { return (
    - + Outgoing webhooks can send alert data to other systems. They can be triggered by various conditions and can use templates to transform data to fit the recipient system. Presets listed below provide a starting point @@ -231,7 +221,7 @@ const Presets = (props: PresetsProps) => { )} - +
    ); @@ -265,7 +255,7 @@ const NewWebhook = (props: NewWebhookProps) => { onTemplateEditClick={onTemplateEditClick} />
    - + {action === WebhookFormActionType.NEW ? ( - +
    @@ -400,7 +390,7 @@ const WebhookTabsContent: React.FC = observer( onTemplateEditClick={onTemplateEditClick} />
    - + @@ -428,7 +418,7 @@ const WebhookTabsContent: React.FC = observer( {action === WebhookFormActionType.NEW ? 'Create' : 'Update'} - +
    diff --git a/grafana-plugin/src/containers/OutgoingWebhookForm/OutgoingWebhookFormFields.tsx b/grafana-plugin/src/containers/OutgoingWebhookForm/OutgoingWebhookFormFields.tsx index aa8111bdf6..0250c06bf7 100644 --- a/grafana-plugin/src/containers/OutgoingWebhookForm/OutgoingWebhookFormFields.tsx +++ b/grafana-plugin/src/containers/OutgoingWebhookForm/OutgoingWebhookFormFields.tsx @@ -112,6 +112,7 @@ export const OutgoingWebhookFormFields: React.FC placeholder="Choose (Optional)" value={field.value} onChange={field.onChange} + dataTestId="team-selector" /> )} @@ -128,6 +129,7 @@ export const OutgoingWebhookFormFields: React.FC error={errors.trigger_type?.message} > { />
    - - - + + + - + Mask by weekdays {isMaskedByWeekdays && ( { disabled={disabled} /> )} - - + + - + - + Limit each shift length {isLimitShiftEnabled && ( { will repeat every day )} - - - - + + + +
    - + Users - +
    { )} showError={Boolean(errors.rolling_users)} /> - +
    - + Current timezone: {store.timezoneStore.selectedTimezoneLabel} - + {shiftId !== 'new' && ( )} - - + +
    @@ -929,9 +917,9 @@ const ShiftPeriod = ({ }, [unitToCreate]); return ( - + {timeUnits.map((unit, index: number, arr) => ( - + )} - + ))} {timeUnits.length === 0 && unitToCreate !== undefined && ( - - - + + + ); diff --git a/grafana-plugin/src/containers/RotationForm/ShiftSwapForm.tsx b/grafana-plugin/src/containers/RotationForm/ShiftSwapForm.tsx index 6a28e61d2c..b8ab15f3be 100644 --- a/grafana-plugin/src/containers/RotationForm/ShiftSwapForm.tsx +++ b/grafana-plugin/src/containers/RotationForm/ShiftSwapForm.tsx @@ -1,6 +1,6 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; -import { Button, Field, HorizontalGroup, IconButton, Input, TextArea, VerticalGroup } from '@grafana/ui'; +import { Button, Field, IconButton, Input, TextArea, Stack } from '@grafana/ui'; import cn from 'classnames/bind'; import dayjs from 'dayjs'; import Draggable from 'react-draggable'; @@ -15,6 +15,7 @@ import { Schedule, ShiftSwap } from 'models/schedule/schedule.types'; import { getUTCString } from 'pages/schedule/Schedule.helpers'; import { useStore } from 'state/useStore'; import { UserActions } from 'utils/authorization/authorization'; +import { StackSize } from 'utils/consts'; import { DateTimePicker } from './parts/DateTimePicker'; import { UserItem } from './parts/UserItem'; @@ -136,13 +137,13 @@ export const ShiftSwapForm = (props: ShiftSwapFormProps) => { )} >
    - - - + + + {isNew && New} {isNew ? 'Shift swap request' : 'Shift swap'} - - + + {!isNew && ( @@ -158,8 +159,8 @@ export const ShiftSwapForm = (props: ShiftSwapFormProps) => { )} - - + +
    {!isNew && ( @@ -168,7 +169,7 @@ export const ShiftSwapForm = (props: ShiftSwapFormProps) => { )} - + { onChange={handleShiftSwapEndChange} /> - +