From 4c049a1a135994c89cbfbb8181984ebc4bcffd67 Mon Sep 17 00:00:00 2001 From: Juan Lulkin Date: Tue, 23 Feb 2021 18:00:55 +0100 Subject: [PATCH] Allows trigger button to render without pager duty key --- .changeset/sour-insects-marry.md | 5 + .../components/TriggerButton/index.test.tsx | 149 ++++++++++++++++++ .../src/components/TriggerButton/index.tsx | 33 ++-- .../TriggerDialog/TriggerDialog.test.tsx | 26 ++- .../TriggerDialog/TriggerDialog.tsx | 7 +- 5 files changed, 189 insertions(+), 31 deletions(-) create mode 100644 .changeset/sour-insects-marry.md create mode 100644 plugins/pagerduty/src/components/TriggerButton/index.test.tsx diff --git a/.changeset/sour-insects-marry.md b/.changeset/sour-insects-marry.md new file mode 100644 index 0000000000..f52f7fd8be --- /dev/null +++ b/.changeset/sour-insects-marry.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-pagerduty': patch +--- + +Allows the TriggerButton component to render when key is missing diff --git a/plugins/pagerduty/src/components/TriggerButton/index.test.tsx b/plugins/pagerduty/src/components/TriggerButton/index.test.tsx new file mode 100644 index 0000000000..390c8143a5 --- /dev/null +++ b/plugins/pagerduty/src/components/TriggerButton/index.test.tsx @@ -0,0 +1,149 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React from 'react'; +import { act, fireEvent, waitFor } from '@testing-library/react'; +import { renderInTestApp } from '@backstage/test-utils'; +import { + ApiRegistry, + alertApiRef, + createApiRef, + ApiProvider, + IdentityApi, + identityApiRef, +} from '@backstage/core'; +import { pagerDutyApiRef } from '../../api'; +import { Entity } from '@backstage/catalog-model'; +import { EntityProvider } from '@backstage/plugin-catalog-react'; +import { TriggerButton } from './'; + +describe('TriggerButton', () => { + const mockIdentityApi: Partial = { + getUserId: () => 'guest@example.com', + }; + + const mockTriggerAlarmFn = jest.fn(); + const mockPagerDutyApi = { + triggerAlarm: mockTriggerAlarmFn, + }; + + const apis = ApiRegistry.from([ + [ + alertApiRef, + createApiRef({ + id: 'core.alert', + description: 'Used to report alerts and forward them to the app', + }), + ], + [identityApiRef, mockIdentityApi], + [pagerDutyApiRef, mockPagerDutyApi], + ]); + + it('renders the trigger button, opens and closes dialog', async () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'pagerduty-test', + annotations: { + 'pagerduty.com/integration-key': 'abc123', + }, + }, + }; + + const { queryByRole, getByRole, getByTestId } = await renderInTestApp( + + + + + , + ); + + expect(getByTestId('trigger-button')).toBeInTheDocument(); + expect(queryByRole('dialog')).not.toBeInTheDocument(); + + const triggerButton = getByTestId('trigger-button'); + expect(triggerButton.textContent).toBe('Create Incident'); + + await act(async () => { + fireEvent.click(triggerButton); + }); + await waitFor(() => { + expect(getByRole('dialog')).toBeInTheDocument(); + }); + + const closeButton = getByTestId('close-button'); + await act(async () => { + fireEvent.click(closeButton); + }); + await waitFor(() => { + expect(queryByRole('dialog')).not.toBeInTheDocument(); + }); + }); + + it('renders the trigger button with children', async () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'pagerduty-test', + annotations: { + 'pagerduty.com/integration-key': 'abc123', + }, + }, + }; + + const { getByTestId } = await renderInTestApp( + + + Send an alert + + , + ); + + const triggerButton = getByTestId('trigger-button'); + expect(triggerButton.textContent).toBe('Send an alert'); + }); + + it('renders a disabled trigger button if entity does not include key', async () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'pagerduty-test', + }, + }; + + const { queryByRole, getByTestId } = await renderInTestApp( + + + + + , + ); + + expect(getByTestId('trigger-button')).toBeInTheDocument(); + + const triggerButton = getByTestId('trigger-button'); + expect(triggerButton.textContent).toBe('Missing integration key'); + + await act(async () => { + fireEvent.click(triggerButton); + }); + await waitFor(() => { + expect(queryByRole('dialog')).not.toBeInTheDocument(); + }); + }); +}); diff --git a/plugins/pagerduty/src/components/TriggerButton/index.tsx b/plugins/pagerduty/src/components/TriggerButton/index.tsx index 833e01d8aa..92d7c61301 100644 --- a/plugins/pagerduty/src/components/TriggerButton/index.tsx +++ b/plugins/pagerduty/src/components/TriggerButton/index.tsx @@ -13,8 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React, { useCallback, PropsWithChildren } from 'react'; -import { createGlobalState } from 'react-use'; +import React, { useCallback, PropsWithChildren, useState } from 'react'; import { makeStyles, Button } from '@material-ui/core'; import { useEntity } from '@backstage/plugin-catalog-react'; import { BackstageTheme } from '@backstage/theme'; @@ -50,8 +49,6 @@ const useStyles = makeStyles(theme => ({ }, })); -export const useShowDialog = createGlobalState(false); - export function TriggerButton({ design, onIncidentCreated, @@ -59,7 +56,7 @@ export function TriggerButton({ }: PropsWithChildren) { const { buttonStyle, triggerAlarm } = useStyles(); const { entity } = useEntity(); - const [dialogShown = false, setDialogShown] = useShowDialog(); + const [dialogShown, setDialogShown] = useState(false); const showDialog = useCallback(() => { setDialogShown(true); @@ -68,9 +65,8 @@ export function TriggerButton({ setDialogShown(false); }, [setDialogShown]); - const integrationKey = entity.metadata.annotations![ - PAGERDUTY_INTEGRATION_KEY - ]; + const integrationKey = + entity.metadata.annotations?.[PAGERDUTY_INTEGRATION_KEY]; return ( <> @@ -79,16 +75,21 @@ export function TriggerButton({ {...(design === 'link' && { color: 'secondary' })} onClick={showDialog} className={design === 'link' ? triggerAlarm : buttonStyle} + disabled={!integrationKey} > - {children ?? 'Create Incident'} + {integrationKey + ? children ?? 'Create Incident' + : 'Missing integration key'} - + {integrationKey && ( + + )} ); } diff --git a/plugins/pagerduty/src/components/TriggerDialog/TriggerDialog.test.tsx b/plugins/pagerduty/src/components/TriggerDialog/TriggerDialog.test.tsx index 8073ab44b5..863061ca5f 100644 --- a/plugins/pagerduty/src/components/TriggerDialog/TriggerDialog.test.tsx +++ b/plugins/pagerduty/src/components/TriggerDialog/TriggerDialog.test.tsx @@ -14,8 +14,8 @@ * limitations under the License. */ import React from 'react'; -import { render, fireEvent, act } from '@testing-library/react'; -import { wrapInTestApp } from '@backstage/test-utils'; +import { fireEvent, act } from '@testing-library/react'; +import { renderInTestApp } from '@backstage/test-utils'; import { ApiRegistry, alertApiRef, @@ -62,18 +62,16 @@ describe('TriggerDialog', () => { }, }; - const { getByText, getByRole, getByTestId } = render( - wrapInTestApp( - - {}} - name={entity.metadata.name} - integrationKey="abc123" - onIncidentCreated={() => {}} - /> - , - ), + const { getByText, getByRole, getByTestId } = await renderInTestApp( + + {}} + name={entity.metadata.name} + integrationKey="abc123" + onIncidentCreated={() => {}} + /> + , ); expect(getByRole('dialog')).toBeInTheDocument(); diff --git a/plugins/pagerduty/src/components/TriggerDialog/TriggerDialog.tsx b/plugins/pagerduty/src/components/TriggerDialog/TriggerDialog.tsx index c2084a41ed..34c3b5a2f7 100644 --- a/plugins/pagerduty/src/components/TriggerDialog/TriggerDialog.tsx +++ b/plugins/pagerduty/src/components/TriggerDialog/TriggerDialog.tsx @@ -140,7 +140,12 @@ export const TriggerDialog = ({ > Trigger Incident -