Skip to content

Commit

Permalink
Add UI tests
Browse files Browse the repository at this point in the history
  • Loading branch information
cnasikas committed Jan 18, 2021
1 parent 61f6cac commit f8ce542
Show file tree
Hide file tree
Showing 8 changed files with 779 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { httpServiceMock } from '../../../../../../../../src/core/public/mocks';
import { getIssueTypes, getFieldsByIssueType, getIssues, getIssue } from './api';

const issueTypesResponse = {
status: 'ok',
data: {
projects: [
{
Expand All @@ -24,9 +25,11 @@ const issueTypesResponse = {
},
],
},
actionId: 'test',
};

const fieldsResponse = {
status: 'ok',
data: {
projects: [
{
Expand Down Expand Up @@ -70,13 +73,18 @@ const fieldsResponse = {
],
},
],
actionId: 'test',
},
};

const issueResponse = {
id: '10267',
key: 'RJ-107',
fields: { summary: 'Test title' },
status: 'ok',
data: {
id: '10267',
key: 'RJ-107',
fields: { summary: 'Test title' },
},
actionId: 'test',
};

const issuesResponse = [issueResponse];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { httpServiceMock } from '../../../../../../../../src/core/public/mocks';
import { getIncidentTypes, getSeverity } from './api';

const incidentTypesResponse = {
status: 'ok',
data: [
{ id: 17, name: 'Communication error (fax; email)' },
{ id: 1001, name: 'Custom type' },
{ id: 21, name: 'Denial of Service' },
{ id: 6, name: 'Improper disposal: digital asset(s)' },
{ id: 7, name: 'Improper disposal: documents / files' },
{ id: 4, name: 'Lost documents / files / records' },
{ id: 3, name: 'Lost PC / laptop / tablet' },
{ id: 1, name: 'Lost PDA / smartphone' },
{ id: 8, name: 'Lost storage device / media' },
{ id: 19, name: 'Malware' },
{ id: 23, name: 'Not an Issue' },
{ id: 18, name: 'Other' },
{ id: 22, name: 'Phishing' },
{ id: 11, name: 'Stolen documents / files / records' },
{ id: 12, name: 'Stolen PC / laptop / tablet' },
{ id: 13, name: 'Stolen PDA / smartphone' },
{ id: 14, name: 'Stolen storage device / media' },
{ id: 20, name: 'System Intrusion' },
{ id: 16, name: 'TBD / Unknown' },
{ id: 15, name: 'Vendor / 3rd party error' },
],
actionId: 'test',
};

const severityResponse = {
status: 'ok',
data: [
{ id: 4, name: 'Low' },
{ id: 5, name: 'Medium' },
{ id: 6, name: 'High' },
],
actionId: 'test',
};

describe('Resilient API', () => {
const http = httpServiceMock.createStartContract();

beforeEach(() => jest.resetAllMocks());

describe('getIncidentTypes', () => {
test('should call get choices API', async () => {
const abortCtrl = new AbortController();
http.post.mockResolvedValueOnce(incidentTypesResponse);
const res = await getIncidentTypes({
http,
signal: abortCtrl.signal,
connectorId: 'test',
});

expect(res).toEqual(incidentTypesResponse);
expect(http.post).toHaveBeenCalledWith('/api/actions/action/test/_execute', {
body: '{"params":{"subAction":"incidentTypes","subActionParams":{}}}',
signal: abortCtrl.signal,
});
});
});

describe('getSeverity', () => {
test('should call get choices API', async () => {
const abortCtrl = new AbortController();
http.post.mockResolvedValueOnce(severityResponse);
const res = await getSeverity({
http,
signal: abortCtrl.signal,
connectorId: 'test',
});

expect(res).toEqual(severityResponse);
expect(http.post).toHaveBeenCalledWith('/api/actions/action/test/_execute', {
body: '{"params":{"subAction":"severity","subActionParams":{}}}',
signal: abortCtrl.signal,
});
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { httpServiceMock } from '../../../../../../../../src/core/public/mocks';
import { getChoices } from './api';

const choicesResponse = {
status: 'ok',
data: [
{
dependent_value: '',
label: '1 - Critical',
value: '1',
},
{
dependent_value: '',
label: '2 - High',
value: '2',
},
{
dependent_value: '',
label: '3 - Moderate',
value: '3',
},
{
dependent_value: '',
label: '4 - Low',
value: '4',
},
{
dependent_value: '',
label: '5 - Planning',
value: '5',
},
],
};

describe('ServiceNow API', () => {
const http = httpServiceMock.createStartContract();

beforeEach(() => jest.resetAllMocks());

describe('getChoices', () => {
test('should call get choices API', async () => {
const abortCtrl = new AbortController();
http.post.mockResolvedValueOnce(choicesResponse);
const res = await getChoices({
http,
signal: abortCtrl.signal,
connectorId: 'test',
field: 'priority',
});

expect(res).toEqual(choicesResponse);
expect(http.post).toHaveBeenCalledWith('/api/actions/action/test/_execute', {
body: '{"params":{"subAction":"getChoices","subActionParams":{"field":"priority"}}}',
signal: abortCtrl.signal,
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,102 +8,110 @@ import { registerBuiltInActionTypes } from '.././index';
import { ActionTypeModel } from '../../../../types';
import { ServiceNowActionConnector } from './types';

const ACTION_TYPE_ID = '.servicenow';
let actionTypeModel: ActionTypeModel;
const SERVICENOW_ACTION_TYPE_ID = '.servicenow';
const SERVICENOW_SIR_ACTION_TYPE_ID = '.servicenow-sir';
let actionTypeRegistry: TypeRegistry<ActionTypeModel>;

beforeAll(() => {
const actionTypeRegistry = new TypeRegistry<ActionTypeModel>();
actionTypeRegistry = new TypeRegistry<ActionTypeModel>();
registerBuiltInActionTypes({ actionTypeRegistry });
const getResult = actionTypeRegistry.get(ACTION_TYPE_ID);
if (getResult !== null) {
actionTypeModel = getResult;
}
});

describe('actionTypeRegistry.get() works', () => {
test('action type static data is as expected', () => {
expect(actionTypeModel.id).toEqual(ACTION_TYPE_ID);
[SERVICENOW_ACTION_TYPE_ID, SERVICENOW_SIR_ACTION_TYPE_ID].forEach((id) => {
test(`${id}: action type static data is as expected`, () => {
const actionTypeModel = actionTypeRegistry.get(id);
expect(actionTypeModel.id).toEqual(id);
});
});
});

describe('servicenow connector validation', () => {
test('connector validation succeeds when connector config is valid', () => {
const actionConnector = {
secrets: {
username: 'user',
password: 'pass',
},
id: 'test',
actionTypeId: '.servicenow',
name: 'ServiceNow',
isPreconfigured: false,
config: {
apiUrl: 'https://dev94428.service-now.com/',
},
} as ServiceNowActionConnector;
[SERVICENOW_ACTION_TYPE_ID, SERVICENOW_SIR_ACTION_TYPE_ID].forEach((id) => {
test(`${id}: connector validation succeeds when connector config is valid`, () => {
const actionTypeModel = actionTypeRegistry.get(id);
const actionConnector = {
secrets: {
username: 'user',
password: 'pass',
},
id: 'test',
actionTypeId: id,
name: 'ServiceNow',
isPreconfigured: false,
config: {
apiUrl: 'https://dev94428.service-now.com/',
},
} as ServiceNowActionConnector;

expect(actionTypeModel.validateConnector(actionConnector)).toEqual({
config: {
errors: {
apiUrl: [],
expect(actionTypeModel.validateConnector(actionConnector)).toEqual({
config: {
errors: {
apiUrl: [],
},
},
},
secrets: {
errors: {
username: [],
password: [],
secrets: {
errors: {
username: [],
password: [],
},
},
},
});
});
});

test('connector validation fails when connector config is not valid', () => {
const actionConnector = ({
secrets: {
username: 'user',
},
id: '.servicenow',
actionTypeId: '.servicenow',
name: 'servicenow',
config: {},
} as unknown) as ServiceNowActionConnector;
test(`${id}: connector validation fails when connector config is not valid`, () => {
const actionTypeModel = actionTypeRegistry.get(id);
const actionConnector = ({
secrets: {
username: 'user',
},
id,
actionTypeId: id,
name: 'servicenow',
config: {},
} as unknown) as ServiceNowActionConnector;

expect(actionTypeModel.validateConnector(actionConnector)).toEqual({
config: {
errors: {
apiUrl: ['URL is required.'],
expect(actionTypeModel.validateConnector(actionConnector)).toEqual({
config: {
errors: {
apiUrl: ['URL is required.'],
},
},
},
secrets: {
errors: {
username: [],
password: ['Password is required.'],
secrets: {
errors: {
username: [],
password: ['Password is required.'],
},
},
},
});
});
});
});

describe('servicenow action params validation', () => {
test('action params validation succeeds when action params is valid', () => {
const actionParams = {
subActionParams: { incident: { short_description: 'some title {{test}}' }, comments: [] },
};
[SERVICENOW_ACTION_TYPE_ID, SERVICENOW_SIR_ACTION_TYPE_ID].forEach((id) => {
test(`${id}: action params validation succeeds when action params is valid`, () => {
const actionTypeModel = actionTypeRegistry.get(id);
const actionParams = {
subActionParams: { incident: { short_description: 'some title {{test}}' }, comments: [] },
};

expect(actionTypeModel.validateParams(actionParams)).toEqual({
errors: { ['subActionParams.incident.short_description']: [] },
expect(actionTypeModel.validateParams(actionParams)).toEqual({
errors: { ['subActionParams.incident.short_description']: [] },
});
});
});

test('params validation fails when body is not valid', () => {
const actionParams = {
subActionParams: { incident: { short_description: '' }, comments: [] },
};
test(`${id}: params validation fails when body is not valid`, () => {
const actionTypeModel = actionTypeRegistry.get(id);
const actionParams = {
subActionParams: { incident: { short_description: '' }, comments: [] },
};

expect(actionTypeModel.validateParams(actionParams)).toEqual({
errors: {
['subActionParams.incident.short_description']: ['Short description is required.'],
},
expect(actionTypeModel.validateParams(actionParams)).toEqual({
errors: {
['subActionParams.incident.short_description']: ['Short description is required.'],
},
});
});
});
});
Loading

0 comments on commit f8ce542

Please sign in to comment.