Allows trigger button to render without pager duty key
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-pagerduty': patch
|
||||
---
|
||||
|
||||
Allows the TriggerButton component to render when key is missing
|
||||
@@ -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<IdentityApi> = {
|
||||
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(
|
||||
<ApiProvider apis={apis}>
|
||||
<EntityProvider entity={entity}>
|
||||
<TriggerButton design="button" />
|
||||
</EntityProvider>
|
||||
</ApiProvider>,
|
||||
);
|
||||
|
||||
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(
|
||||
<ApiProvider apis={apis}>
|
||||
<EntityProvider entity={entity}>
|
||||
<TriggerButton design="button">Send an alert</TriggerButton>
|
||||
</EntityProvider>
|
||||
</ApiProvider>,
|
||||
);
|
||||
|
||||
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(
|
||||
<ApiProvider apis={apis}>
|
||||
<EntityProvider entity={entity}>
|
||||
<TriggerButton design="button" />
|
||||
</EntityProvider>
|
||||
</ApiProvider>,
|
||||
);
|
||||
|
||||
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();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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<BackstageTheme>(theme => ({
|
||||
},
|
||||
}));
|
||||
|
||||
export const useShowDialog = createGlobalState(false);
|
||||
|
||||
export function TriggerButton({
|
||||
design,
|
||||
onIncidentCreated,
|
||||
@@ -59,7 +56,7 @@ export function TriggerButton({
|
||||
}: PropsWithChildren<TriggerButtonProps>) {
|
||||
const { buttonStyle, triggerAlarm } = useStyles();
|
||||
const { entity } = useEntity();
|
||||
const [dialogShown = false, setDialogShown] = useShowDialog();
|
||||
const [dialogShown, setDialogShown] = useState<boolean>(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'}
|
||||
</Button>
|
||||
<TriggerDialog
|
||||
showDialog={dialogShown}
|
||||
handleDialog={hideDialog}
|
||||
name={entity.metadata.name}
|
||||
integrationKey={integrationKey}
|
||||
onIncidentCreated={onIncidentCreated}
|
||||
/>
|
||||
{integrationKey && (
|
||||
<TriggerDialog
|
||||
showDialog={dialogShown}
|
||||
handleDialog={hideDialog}
|
||||
name={entity.metadata.name}
|
||||
integrationKey={integrationKey}
|
||||
onIncidentCreated={onIncidentCreated}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
<ApiProvider apis={apis}>
|
||||
<TriggerDialog
|
||||
showDialog
|
||||
handleDialog={() => {}}
|
||||
name={entity.metadata.name}
|
||||
integrationKey="abc123"
|
||||
onIncidentCreated={() => {}}
|
||||
/>
|
||||
</ApiProvider>,
|
||||
),
|
||||
const { getByText, getByRole, getByTestId } = await renderInTestApp(
|
||||
<ApiProvider apis={apis}>
|
||||
<TriggerDialog
|
||||
showDialog
|
||||
handleDialog={() => {}}
|
||||
name={entity.metadata.name}
|
||||
integrationKey="abc123"
|
||||
onIncidentCreated={() => {}}
|
||||
/>
|
||||
</ApiProvider>,
|
||||
);
|
||||
|
||||
expect(getByRole('dialog')).toBeInTheDocument();
|
||||
|
||||
@@ -140,7 +140,12 @@ export const TriggerDialog = ({
|
||||
>
|
||||
Trigger Incident
|
||||
</Button>
|
||||
<Button id="close" color="primary" onClick={handleDialog}>
|
||||
<Button
|
||||
data-testid="close-button"
|
||||
id="close"
|
||||
color="primary"
|
||||
onClick={handleDialog}
|
||||
>
|
||||
Close
|
||||
</Button>
|
||||
</DialogActions>
|
||||
|
||||
Reference in New Issue
Block a user