tests(splunk-on-call-plugin): add tests
This commit is contained in:
@@ -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,
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user