tests(splunk-on-call-plugin): add tests

This commit is contained in:
Remi
2021-02-05 20:10:49 +01:00
parent 631419926b
commit 8acc9b2e5b
4 changed files with 549 additions and 0 deletions
@@ -0,0 +1,124 @@
/*
* 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 { render, waitFor } from '@testing-library/react';
import { EscalationPolicy } from './EscalationPolicy';
import { wrapInTestApp } from '@backstage/test-utils';
import { User } from '../types';
import { ApiProvider, ApiRegistry } from '@backstage/core';
import { splunkOnCallApiRef } from '../../api';
const MOCKED_USER: User = {
createdAt: '2021-02-01T23:38:38Z',
displayName: 'Test User',
email: 'test@example.com',
firstName: 'FirstNameTest',
lastName: 'LastNameTest',
passwordLastUpdated: '2021-02-01T23:38:38Z',
username: 'test_user',
verified: true,
_selfUrl: '/api-public/v1/user/test_user',
};
const MOCKED_ON_CALL = [
{
team: { name: 'team_example', slug: 'team-zEalMCgwYSA0Lt40' },
oncallNow: [
{
escalationPolicy: { name: 'Example', slug: 'team-zEalMCgwYSA0Lt40' },
users: [{ onCalluser: { username: 'test_user' } }],
},
],
},
];
const mockSplunkOnCallApi = {
getOnCallUsers: () => [],
};
const apis = ApiRegistry.from([[splunkOnCallApiRef, mockSplunkOnCallApi]]);
describe('Escalation', () => {
it('Handles an empty response', async () => {
mockSplunkOnCallApi.getOnCallUsers = jest
.fn()
.mockImplementationOnce(async () => []);
const { getByText, queryByTestId } = render(
wrapInTestApp(
<ApiProvider apis={apis}>
<EscalationPolicy
users={{
[MOCKED_USER.username!]: MOCKED_USER,
}}
team="team_example"
/>
</ApiProvider>,
),
);
await waitFor(() => !queryByTestId('progress'));
expect(getByText('Empty escalation policy')).toBeInTheDocument();
expect(mockSplunkOnCallApi.getOnCallUsers).toHaveBeenCalled();
});
it('Render a list of users', async () => {
mockSplunkOnCallApi.getOnCallUsers = jest
.fn()
.mockImplementationOnce(async () => MOCKED_ON_CALL);
const { getByText, queryByTestId } = render(
wrapInTestApp(
<ApiProvider apis={apis}>
<EscalationPolicy
users={{
[MOCKED_USER.username!]: MOCKED_USER,
}}
team="team_example"
/>
</ApiProvider>,
),
);
await waitFor(() => !queryByTestId('progress'));
expect(getByText('FirstNameTest LastNameTest')).toBeInTheDocument();
expect(getByText('test@example.com')).toBeInTheDocument();
expect(mockSplunkOnCallApi.getOnCallUsers).toHaveBeenCalled();
});
it('Handles errors', async () => {
mockSplunkOnCallApi.getOnCallUsers = jest
.fn()
.mockRejectedValueOnce(new Error('Error message'));
const { getByText, queryByTestId } = render(
wrapInTestApp(
<ApiProvider apis={apis}>
<EscalationPolicy
users={{
[MOCKED_USER.username!]: MOCKED_USER,
}}
team="team_example"
/>
</ApiProvider>,
),
);
await waitFor(() => !queryByTestId('progress'));
expect(
getByText('Error encountered while fetching information. Error message'),
).toBeInTheDocument();
});
});
@@ -0,0 +1,150 @@
/*
* 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 { render, waitFor } from '@testing-library/react';
import { Incidents } from './Incidents';
import { wrapInTestApp } from '@backstage/test-utils';
import {
ApiProvider,
ApiRegistry,
IdentityApi,
identityApiRef,
} from '@backstage/core';
import { splunkOnCallApiRef } from '../../api';
import { Incident, Team } from '../types';
const MOCK_INCIDENT: Incident = {
alertCount: 1,
currentPhase: 'ACKED',
entityDisplayName: 'test-incident',
entityId: 'entityId',
entityState: 'CRITICAL',
entityType: 'SERVICE',
incidentNumber: '1',
lastAlertId: 'lastAlertId',
lastAlertTime: '2021-02-03T00:13:11Z',
routingKey: 'routingdefault',
service: 'test',
startTime: '2021-02-03T00:13:11Z',
pagedTeams: ['team-O9SqT13fsnCstjMi'],
pagedUsers: [],
pagedPolicies: [
{
policy: {
name: 'Generated Direct User Policy for test',
slug: 'directUserPolicySlug-test',
_selfUrl: '/test',
},
},
],
transitions: [{ name: 'ACKED', at: '2021-02-03T01:20:00Z', by: 'test' }],
monitorName: 'vouser-user',
monitorType: 'Manual',
firstAlertUuid: 'firstAlertUuid',
incidentLink: 'https://portal.victorops.com/example',
};
const MOCK_TEAM: Team = {
_selfUrl: '/api-public/v1/team/team-O9SqT13fsnCstjMi',
_membersUrl: '/api-public/v1/team/team-O9SqT13fsnCstjMi/members',
_policiesUrl: '/api-public/v1/team/team-O9SqT13fsnCstjMi/policies',
_adminsUrl: '/api-public/v1/team/team-O9SqT13fsnCstjMi/admins',
name: 'test',
slug: 'team-O9SqT13fsnCstjMi',
memberCount: 1,
version: 1,
isDefaultTeam: false,
};
const mockIdentityApi: Partial<IdentityApi> = {
getUserId: () => 'test',
};
const mockSplunkOnCallApi = {
getIncidents: () => [],
getTeams: () => [],
};
const apis = ApiRegistry.from([
[identityApiRef, mockIdentityApi],
[splunkOnCallApiRef, mockSplunkOnCallApi],
]);
describe('Incidents', () => {
it('Renders an empty state when there are no incidents', async () => {
mockSplunkOnCallApi.getTeams = jest
.fn()
.mockImplementationOnce(async () => [MOCK_TEAM]);
const { getByText, queryByTestId } = render(
wrapInTestApp(
<ApiProvider apis={apis}>
<Incidents refreshIncidents={false} team="test" />
</ApiProvider>,
),
);
await waitFor(() => !queryByTestId('progress'));
expect(getByText('Nice! No incidents found!')).toBeInTheDocument();
});
it('Renders all incidents', async () => {
mockSplunkOnCallApi.getIncidents = jest
.fn()
.mockImplementationOnce(async () => [MOCK_INCIDENT]);
mockSplunkOnCallApi.getTeams = jest
.fn()
.mockImplementationOnce(async () => [MOCK_TEAM]);
const {
getByText,
getByTitle,
getAllByTitle,
getByLabelText,
queryByTestId,
} = render(
wrapInTestApp(
<ApiProvider apis={apis}>
<Incidents team="test" refreshIncidents={false} />
</ApiProvider>,
),
);
await waitFor(() => !queryByTestId('progress'));
expect(getByText('user')).toBeInTheDocument();
expect(getByText('test-incident')).toBeInTheDocument();
expect(getByTitle('ACKED')).toBeInTheDocument();
expect(getByLabelText('Status warning')).toBeInTheDocument();
// assert links, mailto and hrefs, date calculation
expect(getAllByTitle('View in Splunk On-Call').length).toEqual(1);
});
it('Handle errors', async () => {
mockSplunkOnCallApi.getIncidents = jest
.fn()
.mockRejectedValueOnce(new Error('Error occurred'));
const { getByText, queryByTestId } = render(
wrapInTestApp(
<ApiProvider apis={apis}>
<Incidents team="test" refreshIncidents={false} />
</ApiProvider>,
),
);
await waitFor(() => !queryByTestId('progress'));
expect(
getByText('Error encountered while fetching information. Error occurred'),
).toBeInTheDocument();
});
});
@@ -0,0 +1,147 @@
/*
* 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 { render, waitFor, fireEvent, act } from '@testing-library/react';
import { SplunkOnCallCard } from './SplunkOnCallCard';
import { Entity } from '@backstage/catalog-model';
import { wrapInTestApp } from '@backstage/test-utils';
import {
alertApiRef,
ApiProvider,
ApiRegistry,
createApiRef,
} from '@backstage/core';
import {
splunkOnCallApiRef,
UnauthorizedError,
SplunkOnCallClient,
} from '../api';
import { User } from './types';
const MOCKED_USER: User = {
createdAt: '2021-02-01T23:38:38Z',
displayName: 'Test User',
email: 'remi.d45@gmail.com',
firstName: 'FirstNameTest',
lastName: 'LastNameTest',
passwordLastUpdated: '2021-02-01T23:38:38Z',
username: 'test_user',
verified: true,
_selfUrl: '/api-public/v1/user/test_user',
};
const mockSplunkOnCallApi: Partial<SplunkOnCallClient> = {
getUsers: async () => [],
};
const apis = ApiRegistry.from([
[splunkOnCallApiRef, mockSplunkOnCallApi],
[
alertApiRef,
createApiRef({
id: 'core.alert',
description: 'Used to report alerts and forward them to the app',
}),
],
]);
const entity: Entity = {
apiVersion: 'backstage.io/v1alpha1',
kind: 'Component',
metadata: {
name: 'splunkoncall-test',
annotations: {
'splunkoncall.com/integration-key': 'abc123',
},
},
};
describe('PageDutyCard', () => {
it('Render splunkoncall', async () => {
mockSplunkOnCallApi.getUsers = jest
.fn()
.mockImplementationOnce(async () => [MOCKED_USER]);
const { getByText, queryByTestId } = render(
wrapInTestApp(
<ApiProvider apis={apis}>
<SplunkOnCallCard entity={entity} />
</ApiProvider>,
),
);
await waitFor(() => !queryByTestId('progress'));
expect(getByText('Create Incident')).toBeInTheDocument();
expect(getByText('Nice! No incidents found!')).toBeInTheDocument();
expect(getByText('Empty escalation policy')).toBeInTheDocument();
});
it('Handles custom error for missing token', async () => {
mockSplunkOnCallApi.getUsers = jest
.fn()
.mockRejectedValueOnce(new UnauthorizedError());
const { getByText, queryByTestId } = render(
wrapInTestApp(
<ApiProvider apis={apis}>
<SplunkOnCallCard entity={entity} />
</ApiProvider>,
),
);
await waitFor(() => !queryByTestId('progress'));
expect(
getByText('Missing or invalid SplunkOnCall Token'),
).toBeInTheDocument();
});
it('handles general error', async () => {
mockSplunkOnCallApi.getUsers = jest
.fn()
.mockRejectedValueOnce(new Error('An error occurred'));
const { getByText, queryByTestId } = render(
wrapInTestApp(
<ApiProvider apis={apis}>
<SplunkOnCallCard entity={entity} />
</ApiProvider>,
),
);
await waitFor(() => !queryByTestId('progress'));
expect(
getByText(
'Error encountered while fetching information. An error occurred',
),
).toBeInTheDocument();
});
it('opens the dialog when trigger button is clicked', async () => {
mockSplunkOnCallApi.getUsers = jest
.fn()
.mockImplementationOnce(async () => [MOCKED_USER]);
const { getByText, queryByTestId, getByTestId, getByRole } = render(
wrapInTestApp(
<ApiProvider apis={apis}>
<SplunkOnCallCard entity={entity} />
</ApiProvider>,
),
);
await waitFor(() => !queryByTestId('progress'));
expect(getByText('Create Incident')).toBeInTheDocument();
const triggerButton = getByTestId('trigger-button');
await act(async () => {
fireEvent.click(triggerButton);
});
expect(getByRole('dialog')).toBeInTheDocument();
});
});
@@ -0,0 +1,128 @@
/*
* 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 { render, fireEvent, act } from '@testing-library/react';
import { wrapInTestApp } from '@backstage/test-utils';
import {
ApiRegistry,
alertApiRef,
createApiRef,
ApiProvider,
IdentityApi,
identityApiRef,
} from '@backstage/core';
import { splunkOnCallApiRef } from '../../api';
import { TriggerDialog } from './TriggerDialog';
import { User } from '../types';
const MOCKED_USER: User = {
createdAt: '2021-02-01T23:38:38Z',
displayName: 'Test User',
email: 'remi.d45@gmail.com',
firstName: 'FirstNameTest',
lastName: 'LastNameTest',
passwordLastUpdated: '2021-02-01T23:38:38Z',
username: 'test_user',
verified: true,
_selfUrl: '/api-public/v1/user/test_user',
};
describe('TriggerDialog', () => {
const mockIdentityApi: Partial<IdentityApi> = {
getUserId: () => 'guest@example.com',
};
const mockTriggerAlarmFn = jest.fn();
const mockSplunkOnCallApi = {
triggerAlarm: mockTriggerAlarmFn,
getEscalationPolicies: async () => ({
policies: [
{
policy: {
name: 'Example',
slug: 'team-zEalMCgwYSA0Lt40',
_selfUrl: '/api-public/v1/policies/team-zEalMCgwYSA0Lt40',
},
team: { name: 'Example', slug: 'team-zEalMCgwYSA0Lt40' },
},
],
}),
};
const apis = ApiRegistry.from([
[
alertApiRef,
createApiRef({
id: 'core.alert',
description: 'Used to report alerts and forward them to the app',
}),
],
[identityApiRef, mockIdentityApi],
[splunkOnCallApiRef, mockSplunkOnCallApi],
]);
it('open the dialog and trigger an alarm', async () => {
const { getByText, getByRole, getByTestId } = render(
wrapInTestApp(
<ApiProvider apis={apis}>
<TriggerDialog
showDialog
handleDialog={() => {}}
users={[MOCKED_USER]}
onIncidentCreated={() => {}}
/>
</ApiProvider>,
),
);
expect(getByRole('dialog')).toBeInTheDocument();
expect(
getByText('This action will trigger an incident', {
exact: false,
}),
).toBeInTheDocument();
const summary = getByTestId('trigger-summary-input');
const body = getByTestId('trigger-body-input');
const userTarget = getByTestId('trigger-select-user-target');
const behavior = getByTestId('trigger-select-behavior');
const policiesTarget = getByTestId('trigger-select-policies-target');
const description = 'Test Trigger Alarm';
await act(async () => {
fireEvent.change(summary, { target: { value: description } });
fireEvent.change(body, { target: { value: description } });
fireEvent.change(userTarget, { target: { value: ['test_user'] } });
fireEvent.change(behavior, { target: { value: '0' } });
fireEvent.change(policiesTarget, {
target: { value: ['team-zEalMCgwYSA0Lt40'] },
});
});
const triggerButton = getByTestId('trigger-button');
await act(async () => {
fireEvent.click(triggerButton);
});
expect(mockTriggerAlarmFn).toHaveBeenCalled();
expect(mockTriggerAlarmFn).toHaveBeenCalledWith({
summary: description,
details: description,
userName: 'guest@example.com',
targets: [
{ slug: 'test_user', type: 'User' },
{ slug: 'team-zEalMCgwYSA0Lt40', type: 'EscalationPolicy' },
],
isMultiResponder: false,
});
});
});