From b9b6d2d5a71d8a3b74f9e49a0b15cb1b2e66d00a Mon Sep 17 00:00:00 2001 From: Rares Mardare Date: Thu, 17 Nov 2022 13:59:57 +0200 Subject: [PATCH] bring back test for outgoing webhooks --- grafana-plugin/src/PluginPage.tsx | 2 +- .../AlertTemplates/AlertTemplatesForm.tsx | 2 +- .../DefaultPageLayout/DefaultPageLayout.tsx | 2 +- .../IntegrationSettings.tsx | 2 +- .../IntegrationSettings/parts/Autoresolve.tsx | 2 +- .../escalation-chains/EscalationChains.tsx | 2 +- .../src/pages/incident/Incident.tsx | 2 +- .../src/pages/incidents/Incidents.tsx | 2 +- .../src/pages/integrations/Integrations.tsx | 2 +- .../OutgoingWebhooks.test.tsx | 86 +++++++++++++++++++ .../outgoing_webhooks/OutgoingWebhooks.tsx | 2 +- .../src/pages/schedule/Schedule.tsx | 2 +- .../src/pages/schedules/Schedules.tsx | 2 +- .../pages/settings/tabs/Cloud/CloudPage.tsx | 2 +- grafana-plugin/src/pages/users/Users.tsx | 2 +- grafana-plugin/src/state/types.ts | 3 +- grafana-plugin/src/style/global.css | 2 +- grafana-plugin/src/utils/LocationHelper.ts | 1 + 18 files changed, 104 insertions(+), 16 deletions(-) create mode 100644 grafana-plugin/src/pages/outgoing_webhooks/OutgoingWebhooks.test.tsx diff --git a/grafana-plugin/src/PluginPage.tsx b/grafana-plugin/src/PluginPage.tsx index d18b4155..43e0d91f 100644 --- a/grafana-plugin/src/PluginPage.tsx +++ b/grafana-plugin/src/PluginPage.tsx @@ -3,10 +3,10 @@ import React from 'react'; import { PluginPageProps, PluginPage as RealPluginPage } from '@grafana/runtime'; import Header from 'navbar/Header/Header'; +import { pages } from 'pages'; import { isTopNavbar } from 'plugin/GrafanaPluginRootPage.helpers'; import { useStore } from 'state/useStore'; import { useQueryParams } from 'utils/hooks'; -import { pages } from 'pages'; export const PluginPage = (isTopNavbar() ? RealPlugin : PluginPageFallback) as React.ComponentType; diff --git a/grafana-plugin/src/components/AlertTemplates/AlertTemplatesForm.tsx b/grafana-plugin/src/components/AlertTemplates/AlertTemplatesForm.tsx index 1e9d812a..71c38142 100644 --- a/grafana-plugin/src/components/AlertTemplates/AlertTemplatesForm.tsx +++ b/grafana-plugin/src/components/AlertTemplates/AlertTemplatesForm.tsx @@ -18,9 +18,9 @@ import { AlertReceiveChannel } from 'models/alert_receive_channel/alert_receive_ import { Alert } from 'models/alertgroup/alertgroup.types'; import { makeRequest } from 'network'; import { UserAction } from 'state/userAction'; +import LocationHelper from 'utils/LocationHelper'; import styles from './AlertTemplatesForm.module.css'; -import LocationHelper from 'utils/LocationHelper'; const cx = cn.bind(styles); diff --git a/grafana-plugin/src/containers/DefaultPageLayout/DefaultPageLayout.tsx b/grafana-plugin/src/containers/DefaultPageLayout/DefaultPageLayout.tsx index 872384ba..f5b266c5 100644 --- a/grafana-plugin/src/containers/DefaultPageLayout/DefaultPageLayout.tsx +++ b/grafana-plugin/src/containers/DefaultPageLayout/DefaultPageLayout.tsx @@ -11,6 +11,7 @@ import { getIfChatOpsConnected } from 'containers/DefaultPageLayout/helper'; import { AppFeature } from 'state/features'; import { useStore } from 'state/useStore'; import { UserAction } from 'state/userAction'; +import LocationHelper from 'utils/LocationHelper'; import { GRAFANA_LICENSE_OSS } from 'utils/consts'; import { useForceUpdate } from 'utils/hooks'; import { getItem, setItem } from 'utils/localStorage'; @@ -19,7 +20,6 @@ import sanitize from 'utils/sanitize'; import { getSlackMessage } from './DefaultPageLayout.helpers'; import styles from './DefaultPageLayout.module.scss'; import { SlackError } from './DefaultPageLayout.types'; -import LocationHelper from 'utils/LocationHelper'; const cx = cn.bind(styles); diff --git a/grafana-plugin/src/containers/IntegrationSettings/IntegrationSettings.tsx b/grafana-plugin/src/containers/IntegrationSettings/IntegrationSettings.tsx index f69dbff8..f6652400 100644 --- a/grafana-plugin/src/containers/IntegrationSettings/IntegrationSettings.tsx +++ b/grafana-plugin/src/containers/IntegrationSettings/IntegrationSettings.tsx @@ -14,12 +14,12 @@ import { AlertReceiveChannel } from 'models/alert_receive_channel/alert_receive_ import { Alert } from 'models/alertgroup/alertgroup.types'; import { useStore } from 'state/useStore'; import { openNotification } from 'utils'; +import LocationHelper from 'utils/LocationHelper'; import { IntegrationSettingsTab } from './IntegrationSettings.types'; import Autoresolve from './parts/Autoresolve'; import styles from 'containers/IntegrationSettings/IntegrationSettings.module.css'; -import LocationHelper from 'utils/LocationHelper'; const cx = cn.bind(styles); diff --git a/grafana-plugin/src/containers/IntegrationSettings/parts/Autoresolve.tsx b/grafana-plugin/src/containers/IntegrationSettings/parts/Autoresolve.tsx index e2f10650..420c64a1 100644 --- a/grafana-plugin/src/containers/IntegrationSettings/parts/Autoresolve.tsx +++ b/grafana-plugin/src/containers/IntegrationSettings/parts/Autoresolve.tsx @@ -14,9 +14,9 @@ import { Team } from 'models/team/team.types'; import { useStore } from 'state/useStore'; import { UserAction } from 'state/userAction'; import { openErrorNotification, openNotification } from 'utils'; +import LocationHelper from 'utils/LocationHelper'; import styles from 'containers/IntegrationSettings/parts/Autoresolve.module.css'; -import LocationHelper from 'utils/LocationHelper'; const cx = cn.bind(styles); diff --git a/grafana-plugin/src/pages/escalation-chains/EscalationChains.tsx b/grafana-plugin/src/pages/escalation-chains/EscalationChains.tsx index 52e3ec01..42f66cd7 100644 --- a/grafana-plugin/src/pages/escalation-chains/EscalationChains.tsx +++ b/grafana-plugin/src/pages/escalation-chains/EscalationChains.tsx @@ -30,9 +30,9 @@ import { pages } from 'pages'; import { WithStoreProps } from 'state/types'; import { UserAction } from 'state/userAction'; import { withMobXProviderContext } from 'state/withStore'; +import LocationHelper from 'utils/LocationHelper'; import styles from './EscalationChains.module.css'; -import LocationHelper from 'utils/LocationHelper'; const cx = cn.bind(styles); diff --git a/grafana-plugin/src/pages/incident/Incident.tsx b/grafana-plugin/src/pages/incident/Incident.tsx index c8d8bc0b..528c28e0 100644 --- a/grafana-plugin/src/pages/incident/Incident.tsx +++ b/grafana-plugin/src/pages/incident/Incident.tsx @@ -52,12 +52,12 @@ import { useStore } from 'state/useStore'; import { UserAction } from 'state/userAction'; import { withMobXProviderContext } from 'state/withStore'; import { openNotification } from 'utils'; +import LocationHelper from 'utils/LocationHelper'; import sanitize from 'utils/sanitize'; import { getActionButtons, getIncidentStatusTag, renderRelatedUsers } from './Incident.helpers'; import styles from './Incident.module.css'; -import LocationHelper from 'utils/LocationHelper'; const cx = cn.bind(styles); diff --git a/grafana-plugin/src/pages/incidents/Incidents.tsx b/grafana-plugin/src/pages/incidents/Incidents.tsx index aa7bf867..5b6e0014 100644 --- a/grafana-plugin/src/pages/incidents/Incidents.tsx +++ b/grafana-plugin/src/pages/incidents/Incidents.tsx @@ -27,11 +27,11 @@ import { move } from 'state/helpers'; import { PageProps, WithStoreProps } from 'state/types'; import { UserAction } from 'state/userAction'; import { withMobXProviderContext } from 'state/withStore'; +import LocationHelper from 'utils/LocationHelper'; import SilenceDropdown from './parts/SilenceDropdown'; import styles from './Incidents.module.css'; -import LocationHelper from 'utils/LocationHelper'; const cx = cn.bind(styles); diff --git a/grafana-plugin/src/pages/integrations/Integrations.tsx b/grafana-plugin/src/pages/integrations/Integrations.tsx index ddb4774a..e2d5ee5b 100644 --- a/grafana-plugin/src/pages/integrations/Integrations.tsx +++ b/grafana-plugin/src/pages/integrations/Integrations.tsx @@ -29,9 +29,9 @@ import { pages } from 'pages'; import { WithStoreProps } from 'state/types'; import { UserAction } from 'state/userAction'; import { withMobXProviderContext } from 'state/withStore'; +import LocationHelper from 'utils/LocationHelper'; import styles from './Integrations.module.css'; -import LocationHelper from 'utils/LocationHelper'; const cx = cn.bind(styles); diff --git a/grafana-plugin/src/pages/outgoing_webhooks/OutgoingWebhooks.test.tsx b/grafana-plugin/src/pages/outgoing_webhooks/OutgoingWebhooks.test.tsx new file mode 100644 index 00000000..c2c9f9f4 --- /dev/null +++ b/grafana-plugin/src/pages/outgoing_webhooks/OutgoingWebhooks.test.tsx @@ -0,0 +1,86 @@ +import 'jest/matchMedia.ts'; +import React from 'react'; + +import { describe, expect, test } from '@jest/globals'; +import { render, screen, waitFor } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import outgoingWebhooksStub from 'jest/outgoingWebhooksStub'; + +import { OutgoingWebhook } from 'models/outgoing_webhook/outgoing_webhook.types'; +import { OutgoingWebhooks } from 'pages/outgoing_webhooks/OutgoingWebhooks'; + +const outgoingWebhooks = outgoingWebhooksStub as OutgoingWebhook[]; +const outgoingWebhookStore = () => ({ + loadItem: () => Promise.resolve(outgoingWebhooks[0]), + updateItems: () => Promise.resolve(), + getSearchResult: () => outgoingWebhooks, + items: outgoingWebhooks.reduce((prev, current) => { + prev[current.id] = current; + return prev; + }, {}), +}); + +jest.mock('plugin/GrafanaPluginRootPage.helpers', () => ({ + isTopNavbar: () => false, +})); + +jest.mock('@grafana/runtime', () => ({ + config: { + featureToggles: { + topNav: false, + }, + }, +})); + +jest.mock('state/useStore', () => ({ + useStore: () => ({ + outgoingWebhookStore: outgoingWebhookStore(), + isUserActionAllowed: jest.fn().mockReturnValue(true), + }), +})); + +jest.mock('@grafana/runtime', () => ({ + getLocationSrv: jest.fn(), +})); + +describe('OutgoingWebhooks', () => { + const storeMock = { + isUserActionAllowed: jest.fn().mockReturnValue(true), + outgoingWebhookStore: outgoingWebhookStore(), + }; + + beforeAll(() => { + console.warn = () => {}; + console.error = () => {}; + }); + + test('It renders all retrieved webhooks', async () => { + render(); + + const gTable = screen.queryByTestId('test__gTable'); + const rows = gTable.querySelectorAll('tbody tr'); + + await waitFor(() => { + expect(() => queryEditForm()).toThrow(); // edit doesn't show for [id=undefined] + expect(rows.length).toBe(outgoingWebhooks.length); + }); + }); + + test('It opens Edit View if [id] is supplied', async () => { + const id = outgoingWebhooks[0].id; + render(); + + expect(() => queryEditForm()).toThrow(); // before updates kick in + await waitFor(() => { + expect(queryEditForm()).toBeDefined(); // edit shows for [id=?] + }); + }); + + function getProps(id: OutgoingWebhook['id'] = undefined): any { + return { store: storeMock, query: { id } }; + } + + function queryEditForm(): HTMLElement { + return screen.getByTestId('test__outgoingWebhookEditForm'); + } +}); diff --git a/grafana-plugin/src/pages/outgoing_webhooks/OutgoingWebhooks.tsx b/grafana-plugin/src/pages/outgoing_webhooks/OutgoingWebhooks.tsx index bb30c811..68bc5e76 100644 --- a/grafana-plugin/src/pages/outgoing_webhooks/OutgoingWebhooks.tsx +++ b/grafana-plugin/src/pages/outgoing_webhooks/OutgoingWebhooks.tsx @@ -23,9 +23,9 @@ import { pages } from 'pages'; import { PageProps, WithStoreProps } from 'state/types'; import { UserAction } from 'state/userAction'; import { withMobXProviderContext } from 'state/withStore'; +import LocationHelper from 'utils/LocationHelper'; import styles from './OutgoingWebhooks.module.css'; -import LocationHelper from 'utils/LocationHelper'; const cx = cn.bind(styles); diff --git a/grafana-plugin/src/pages/schedule/Schedule.tsx b/grafana-plugin/src/pages/schedule/Schedule.tsx index b3c7e3e2..424c9920 100644 --- a/grafana-plugin/src/pages/schedule/Schedule.tsx +++ b/grafana-plugin/src/pages/schedule/Schedule.tsx @@ -25,11 +25,11 @@ import { pages } from 'pages'; import { PageProps, WithStoreProps } from 'state/types'; import { UserAction } from 'state/userAction'; import { withMobXProviderContext } from 'state/withStore'; +import LocationHelper from 'utils/LocationHelper'; import { getStartOfWeek } from './Schedule.helpers'; import styles from './Schedule.module.css'; -import LocationHelper from 'utils/LocationHelper'; const cx = cn.bind(styles); diff --git a/grafana-plugin/src/pages/schedules/Schedules.tsx b/grafana-plugin/src/pages/schedules/Schedules.tsx index 9c853186..18d6ca52 100644 --- a/grafana-plugin/src/pages/schedules/Schedules.tsx +++ b/grafana-plugin/src/pages/schedules/Schedules.tsx @@ -30,9 +30,9 @@ import { getStartOfWeek } from 'pages/schedule/Schedule.helpers'; import { WithStoreProps } from 'state/types'; import { UserAction } from 'state/userAction'; import { withMobXProviderContext } from 'state/withStore'; +import LocationHelper from 'utils/LocationHelper'; import styles from './Schedules.module.css'; -import LocationHelper from 'utils/LocationHelper'; const cx = cn.bind(styles); diff --git a/grafana-plugin/src/pages/settings/tabs/Cloud/CloudPage.tsx b/grafana-plugin/src/pages/settings/tabs/Cloud/CloudPage.tsx index e94419a0..17ebd610 100644 --- a/grafana-plugin/src/pages/settings/tabs/Cloud/CloudPage.tsx +++ b/grafana-plugin/src/pages/settings/tabs/Cloud/CloudPage.tsx @@ -14,9 +14,9 @@ import { WithStoreProps } from 'state/types'; import { useStore } from 'state/useStore'; import { withMobXProviderContext } from 'state/withStore'; import { openErrorNotification } from 'utils'; +import LocationHelper from 'utils/LocationHelper'; import styles from './CloudPage.module.css'; -import LocationHelper from 'utils/LocationHelper'; const cx = cn.bind(styles); diff --git a/grafana-plugin/src/pages/users/Users.tsx b/grafana-plugin/src/pages/users/Users.tsx index 1f943fe2..dfd44a3d 100644 --- a/grafana-plugin/src/pages/users/Users.tsx +++ b/grafana-plugin/src/pages/users/Users.tsx @@ -25,11 +25,11 @@ import { pages } from 'pages'; import { PageProps, WithStoreProps } from 'state/types'; import { UserAction } from 'state/userAction'; import { withMobXProviderContext } from 'state/withStore'; +import LocationHelper from 'utils/LocationHelper'; import { getRealFilters, getUserRowClassNameFn } from './Users.helpers'; import styles from './Users.module.css'; -import LocationHelper from 'utils/LocationHelper'; const cx = cn.bind(styles); diff --git a/grafana-plugin/src/state/types.ts b/grafana-plugin/src/state/types.ts index 5cbc2fa6..9f9eccbd 100644 --- a/grafana-plugin/src/state/types.ts +++ b/grafana-plugin/src/state/types.ts @@ -1,4 +1,5 @@ import { AppPluginMeta, KeyValue } from '@grafana/data'; + import { RootStore } from 'state/index'; export interface WithStoreProps { @@ -7,7 +8,7 @@ export interface WithStoreProps { export interface PageProps { meta: AppPluginMeta; - query: KeyValue + query: KeyValue; } export interface SelectOption { diff --git a/grafana-plugin/src/style/global.css b/grafana-plugin/src/style/global.css index e7590d45..fe3e65a2 100644 --- a/grafana-plugin/src/style/global.css +++ b/grafana-plugin/src/style/global.css @@ -42,4 +42,4 @@ .page-title { margin-bottom: 16px; -} \ No newline at end of file +} diff --git a/grafana-plugin/src/utils/LocationHelper.ts b/grafana-plugin/src/utils/LocationHelper.ts index 653db17c..ce233afd 100644 --- a/grafana-plugin/src/utils/LocationHelper.ts +++ b/grafana-plugin/src/utils/LocationHelper.ts @@ -1,5 +1,6 @@ import { KeyValue } from '@grafana/data'; import { locationService } from '@grafana/runtime'; + import { getQueryParams } from 'plugin/GrafanaPluginRootPage.helpers'; class LocationHelper {