-
+
+
+
+ }
+ iconType="beaker"
+ body={
+
+ }
+ actions={
+
+
+
+ }
/>
-
- {title} }}
- />
-
-
-
-
-
+
);
}
diff --git a/src/plugins/visualize/public/application/components/visualize_listing.tsx b/src/plugins/visualize/public/application/components/visualize_listing.tsx
index 2edabbf46f9d8..718bd2ed343ce 100644
--- a/src/plugins/visualize/public/application/components/visualize_listing.tsx
+++ b/src/plugins/visualize/public/application/components/visualize_listing.tsx
@@ -21,7 +21,9 @@ import './visualize_listing.scss';
import React, { useCallback, useRef, useMemo, useEffect } from 'react';
import { i18n } from '@kbn/i18n';
-import { useUnmount, useMount } from 'react-use';
+import useUnmount from 'react-use/lib/useUnmount';
+import useMount from 'react-use/lib/useMount';
+
import { useLocation } from 'react-router-dom';
import { SavedObjectsFindOptionsReference } from '../../../../../core/public';
diff --git a/test/api_integration/apis/saved_objects/find.js b/test/api_integration/apis/saved_objects/find.js
index e5da46644672b..8e8730b1e574a 100644
--- a/test/api_integration/apis/saved_objects/find.js
+++ b/test/api_integration/apis/saved_objects/find.js
@@ -160,7 +160,7 @@ export default function ({ getService }) {
});
describe('wildcard namespace', () => {
- it('should return 200 with individual responses from the default namespace', async () =>
+ it('should return 200 with individual responses from the all namespaces', async () =>
await supertest
.get('/api/saved_objects/_find?type=visualization&fields=title&namespaces=*')
.expect(200)
@@ -168,7 +168,7 @@ export default function ({ getService }) {
expect(resp.body).to.eql({
page: 1,
per_page: 20,
- total: 1,
+ total: 2,
saved_objects: [
{
type: 'visualization',
@@ -189,6 +189,27 @@ export default function ({ getService }) {
],
updated_at: '2017-09-21T18:51:23.794Z',
},
+ {
+ attributes: {
+ title: 'Count of requests',
+ },
+ id: 'dd7caf20-9efd-11e7-acb3-3dab96693fab',
+ migrationVersion: {
+ visualization: '7.10.0',
+ },
+ namespaces: ['foo-ns'],
+ references: [
+ {
+ id: '91200a00-9efd-11e7-acb3-3dab96693fab',
+ name: 'kibanaSavedObjectMeta.searchSourceJSON.index',
+ type: 'index-pattern',
+ },
+ ],
+ score: 0,
+ type: 'visualization',
+ updated_at: '2017-09-21T18:51:23.794Z',
+ version: 'WzYsMV0=',
+ },
],
});
expect(resp.body.saved_objects[0].migrationVersion).to.be.ok();
diff --git a/test/functional/apps/management/_import_objects.ts b/test/functional/apps/management/_import_objects.ts
index 4a7a85c738fc2..52428c944d666 100644
--- a/test/functional/apps/management/_import_objects.ts
+++ b/test/functional/apps/management/_import_objects.ts
@@ -37,7 +37,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
describe('import objects', function describeIndexTests() {
describe('.ndjson file', () => {
beforeEach(async function () {
- // delete .kibana index and then wait for Kibana to re-create it
await kibanaServer.uiSettings.replace({});
await PageObjects.settings.navigateTo();
await esArchiver.load('management');
@@ -471,16 +470,20 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
);
});
- it('should display an explicit error message when importing a file bigger than allowed', async () => {
- await PageObjects.savedObjects.importFile(
- path.join(__dirname, 'exports', '_import_too_big.ndjson')
- );
+ describe('when bigger than savedObjects.maxImportPayloadBytes (not Cloud)', function () {
+ // see --savedObjects.maxImportPayloadBytes in config file
+ this.tags(['skipCloud']);
+ it('should display an explicit error message when importing a file bigger than allowed', async () => {
+ await PageObjects.savedObjects.importFile(
+ path.join(__dirname, 'exports', '_import_too_big.ndjson')
+ );
- await PageObjects.savedObjects.checkImportError();
+ await PageObjects.savedObjects.checkImportError();
- const errorText = await PageObjects.savedObjects.getImportErrorText();
+ const errorText = await PageObjects.savedObjects.getImportErrorText();
- expect(errorText).to.contain(`Payload content length greater than maximum allowed`);
+ expect(errorText).to.contain(`Payload content length greater than maximum allowed`);
+ });
});
it('should display an explicit error message when importing an invalid file', async () => {
diff --git a/test/functional/apps/management/_mgmt_import_saved_objects.js b/test/functional/apps/management/_mgmt_import_saved_objects.js
index 3a9f8665fd33b..d479a7006d0f8 100644
--- a/test/functional/apps/management/_mgmt_import_saved_objects.js
+++ b/test/functional/apps/management/_mgmt_import_saved_objects.js
@@ -29,6 +29,7 @@ export default function ({ getService, getPageObjects }) {
describe('mgmt saved objects', function describeIndexTests() {
beforeEach(async function () {
+ await esArchiver.load('empty_kibana');
await esArchiver.load('discover');
await PageObjects.settings.navigateTo();
});
diff --git a/test/functional/apps/management/_scripted_fields.js b/test/functional/apps/management/_scripted_fields.js
index 6da9ebed0538a..5ca01f239e762 100644
--- a/test/functional/apps/management/_scripted_fields.js
+++ b/test/functional/apps/management/_scripted_fields.js
@@ -198,35 +198,44 @@ export default function ({ getService, getPageObjects }) {
});
it('should visualize scripted field in vertical bar chart', async function () {
- const expectedChartValues = [
- ['14', '31'],
- ['10', '29'],
- ['7', '24'],
- ['11', '24'],
- ['12', '23'],
- ['20', '23'],
- ['19', '21'],
- ['6', '20'],
- ['17', '20'],
- ['30', '20'],
- ['13', '19'],
- ['18', '18'],
- ['16', '17'],
- ['5', '16'],
- ['8', '16'],
- ['15', '14'],
- ['3', '13'],
- ['2', '12'],
- ['9', '10'],
- ['4', '9'],
- ];
await filterBar.removeAllFilters();
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName);
await PageObjects.header.waitUntilLoadingHasFinished();
- await inspector.open();
- await inspector.setTablePageSize(50);
- await inspector.expectTableData(expectedChartValues);
+ if (await PageObjects.common.isOss()) {
+ // OSS renders a vertical bar chart and we check the data in the Inspect panel
+ const expectedChartValues = [
+ ['14', '31'],
+ ['10', '29'],
+ ['7', '24'],
+ ['11', '24'],
+ ['12', '23'],
+ ['20', '23'],
+ ['19', '21'],
+ ['6', '20'],
+ ['17', '20'],
+ ['30', '20'],
+ ['13', '19'],
+ ['18', '18'],
+ ['16', '17'],
+ ['5', '16'],
+ ['8', '16'],
+ ['15', '14'],
+ ['3', '13'],
+ ['2', '12'],
+ ['9', '10'],
+ ['4', '9'],
+ ];
+
+ await inspector.open();
+ await inspector.setTablePageSize(50);
+ await inspector.expectTableData(expectedChartValues);
+ } else {
+ // verify Lens opens a visualization
+ expect(await testSubjects.getVisibleTextAll('lns-dimensionTrigger')).to.contain(
+ 'Average of ram_Pain1'
+ );
+ }
});
});
@@ -309,11 +318,19 @@ export default function ({ getService, getPageObjects }) {
it('should visualize scripted field in vertical bar chart', async function () {
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName2);
await PageObjects.header.waitUntilLoadingHasFinished();
- await inspector.open();
- await inspector.expectTableData([
- ['good', '359'],
- ['bad', '27'],
- ]);
+ if (await PageObjects.common.isOss()) {
+ // OSS renders a vertical bar chart and we check the data in the Inspect panel
+ await inspector.open();
+ await inspector.expectTableData([
+ ['good', '359'],
+ ['bad', '27'],
+ ]);
+ } else {
+ // verify Lens opens a visualization
+ expect(await testSubjects.getVisibleTextAll('lns-dimensionTrigger')).to.contain(
+ 'Top values of painString'
+ );
+ }
});
});
@@ -397,11 +414,19 @@ export default function ({ getService, getPageObjects }) {
it('should visualize scripted field in vertical bar chart', async function () {
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName2);
await PageObjects.header.waitUntilLoadingHasFinished();
- await inspector.open();
- await inspector.expectTableData([
- ['true', '359'],
- ['false', '27'],
- ]);
+ if (await PageObjects.common.isOss()) {
+ // OSS renders a vertical bar chart and we check the data in the Inspect panel
+ await inspector.open();
+ await inspector.expectTableData([
+ ['true', '359'],
+ ['false', '27'],
+ ]);
+ } else {
+ // verify Lens opens a visualization
+ expect(await testSubjects.getVisibleTextAll('lns-dimensionTrigger')).to.contain(
+ 'Top values of painBool'
+ );
+ }
});
});
@@ -488,30 +513,39 @@ export default function ({ getService, getPageObjects }) {
it('should visualize scripted field in vertical bar chart', async function () {
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName2);
await PageObjects.header.waitUntilLoadingHasFinished();
- await inspector.open();
- await inspector.setTablePageSize(50);
- await inspector.expectTableData([
- ['2015-09-17 20:00', '1'],
- ['2015-09-17 21:00', '1'],
- ['2015-09-17 23:00', '1'],
- ['2015-09-18 00:00', '1'],
- ['2015-09-18 03:00', '1'],
- ['2015-09-18 04:00', '1'],
- ['2015-09-18 04:00', '1'],
- ['2015-09-18 04:00', '1'],
- ['2015-09-18 04:00', '1'],
- ['2015-09-18 05:00', '1'],
- ['2015-09-18 05:00', '1'],
- ['2015-09-18 05:00', '1'],
- ['2015-09-18 05:00', '1'],
- ['2015-09-18 06:00', '1'],
- ['2015-09-18 06:00', '1'],
- ['2015-09-18 06:00', '1'],
- ['2015-09-18 06:00', '1'],
- ['2015-09-18 07:00', '1'],
- ['2015-09-18 07:00', '1'],
- ['2015-09-18 07:00', '1'],
- ]);
+
+ if (await PageObjects.common.isOss()) {
+ // OSS renders a vertical bar chart and we check the data in the Inspect panel
+ await inspector.open();
+ await inspector.setTablePageSize(50);
+ await inspector.expectTableData([
+ ['2015-09-17 20:00', '1'],
+ ['2015-09-17 21:00', '1'],
+ ['2015-09-17 23:00', '1'],
+ ['2015-09-18 00:00', '1'],
+ ['2015-09-18 03:00', '1'],
+ ['2015-09-18 04:00', '1'],
+ ['2015-09-18 04:00', '1'],
+ ['2015-09-18 04:00', '1'],
+ ['2015-09-18 04:00', '1'],
+ ['2015-09-18 05:00', '1'],
+ ['2015-09-18 05:00', '1'],
+ ['2015-09-18 05:00', '1'],
+ ['2015-09-18 05:00', '1'],
+ ['2015-09-18 06:00', '1'],
+ ['2015-09-18 06:00', '1'],
+ ['2015-09-18 06:00', '1'],
+ ['2015-09-18 06:00', '1'],
+ ['2015-09-18 07:00', '1'],
+ ['2015-09-18 07:00', '1'],
+ ['2015-09-18 07:00', '1'],
+ ]);
+ } else {
+ // verify Lens opens a visualization
+ expect(await testSubjects.getVisibleTextAll('lns-dimensionTrigger')).to.contain(
+ 'painDate'
+ );
+ }
});
});
});
diff --git a/test/plugin_functional/plugins/data_search/server/plugin.ts b/test/plugin_functional/plugins/data_search/server/plugin.ts
index e016ef56802f3..ca22e82188403 100644
--- a/test/plugin_functional/plugins/data_search/server/plugin.ts
+++ b/test/plugin_functional/plugins/data_search/server/plugin.ts
@@ -58,14 +58,16 @@ export class DataSearchTestPlugin
},
},
async (context, req, res) => {
- const [{ savedObjects }, { data }] = await core.getStartServices();
+ const [{ savedObjects, elasticsearch }, { data }] = await core.getStartServices();
const service = await data.search.searchSource.asScoped(req);
+ const clusterClient = elasticsearch.client.asScoped(req).asCurrentUser;
const savedObjectsClient = savedObjects.getScopedClient(req);
// Since the index pattern ID can change on each test run, we need
// to look it up on the fly and insert it into the request.
const indexPatterns = await data.indexPatterns.indexPatternsServiceFactory(
- savedObjectsClient
+ savedObjectsClient,
+ clusterClient
);
const ids = await indexPatterns.getIds();
// @ts-expect-error Force overwriting the request
diff --git a/test/plugin_functional/plugins/index_patterns/server/plugin.ts b/test/plugin_functional/plugins/index_patterns/server/plugin.ts
index a54502b740211..c05b71b834c70 100644
--- a/test/plugin_functional/plugins/index_patterns/server/plugin.ts
+++ b/test/plugin_functional/plugins/index_patterns/server/plugin.ts
@@ -36,13 +36,35 @@ export class IndexPatternsTestPlugin
public setup(core: CoreSetup
) {
const router = core.http.createRouter();
+ router.post(
+ {
+ path: '/api/index-patterns-plugin/create',
+ validate: {
+ body: schema.object({}, { unknowns: 'allow' }),
+ },
+ },
+ async (context, req, res) => {
+ const [{ savedObjects, elasticsearch }, { data }] = await core.getStartServices();
+ const savedObjectsClient = savedObjects.getScopedClient(req);
+ const service = await data.indexPatterns.indexPatternsServiceFactory(
+ savedObjectsClient,
+ elasticsearch.client.asScoped(req).asCurrentUser
+ );
+ const ids = await service.createAndSave(req.body);
+ return res.ok({ body: ids });
+ }
+ );
+
router.get(
{ path: '/api/index-patterns-plugin/get-all', validate: false },
async (context, req, res) => {
- const [{ savedObjects }, { data }] = await core.getStartServices();
+ const [{ savedObjects, elasticsearch }, { data }] = await core.getStartServices();
const savedObjectsClient = savedObjects.getScopedClient(req);
- const service = await data.indexPatterns.indexPatternsServiceFactory(savedObjectsClient);
- const ids = await service.getIds();
+ const service = await data.indexPatterns.indexPatternsServiceFactory(
+ savedObjectsClient,
+ elasticsearch.client.asScoped(req).asCurrentUser
+ );
+ const ids = await service.getIds(true);
return res.ok({ body: ids });
}
);
@@ -58,9 +80,12 @@ export class IndexPatternsTestPlugin
},
async (context, req, res) => {
const id = (req.params as Record).id;
- const [{ savedObjects }, { data }] = await core.getStartServices();
+ const [{ savedObjects, elasticsearch }, { data }] = await core.getStartServices();
const savedObjectsClient = savedObjects.getScopedClient(req);
- const service = await data.indexPatterns.indexPatternsServiceFactory(savedObjectsClient);
+ const service = await data.indexPatterns.indexPatternsServiceFactory(
+ savedObjectsClient,
+ elasticsearch.client.asScoped(req).asCurrentUser
+ );
const ip = await service.get(id);
return res.ok({ body: ip.toSpec() });
}
@@ -76,10 +101,13 @@ export class IndexPatternsTestPlugin
},
},
async (context, req, res) => {
- const [{ savedObjects }, { data }] = await core.getStartServices();
+ const [{ savedObjects, elasticsearch }, { data }] = await core.getStartServices();
const id = (req.params as Record).id;
const savedObjectsClient = savedObjects.getScopedClient(req);
- const service = await data.indexPatterns.indexPatternsServiceFactory(savedObjectsClient);
+ const service = await data.indexPatterns.indexPatternsServiceFactory(
+ savedObjectsClient,
+ elasticsearch.client.asScoped(req).asCurrentUser
+ );
const ip = await service.get(id);
await service.updateSavedObject(ip);
return res.ok();
@@ -96,10 +124,13 @@ export class IndexPatternsTestPlugin
},
},
async (context, req, res) => {
- const [{ savedObjects }, { data }] = await core.getStartServices();
+ const [{ savedObjects, elasticsearch }, { data }] = await core.getStartServices();
const id = (req.params as Record).id;
const savedObjectsClient = savedObjects.getScopedClient(req);
- const service = await data.indexPatterns.indexPatternsServiceFactory(savedObjectsClient);
+ const service = await data.indexPatterns.indexPatternsServiceFactory(
+ savedObjectsClient,
+ elasticsearch.client.asScoped(req).asCurrentUser
+ );
await service.delete(id);
return res.ok();
}
diff --git a/test/plugin_functional/test_suites/data_plugin/index_patterns.ts b/test/plugin_functional/test_suites/data_plugin/index_patterns.ts
index 2c846dc780311..2e94f61c7ded8 100644
--- a/test/plugin_functional/test_suites/data_plugin/index_patterns.ts
+++ b/test/plugin_functional/test_suites/data_plugin/index_patterns.ts
@@ -23,16 +23,25 @@ import '../../plugins/core_provider_plugin/types';
export default function ({ getService }: PluginFunctionalProviderContext) {
const supertest = getService('supertest');
- // skipping the tests as it deletes index patterns created by other test causing unexpected failures
- // https://github.com/elastic/kibana/issues/79886
- describe.skip('index patterns', function () {
+ describe('index patterns', function () {
let indexPatternId = '';
- it('can get all ids', async () => {
- const body = await (await supertest.get('/api/index-patterns-plugin/get-all').expect(200))
- .body;
- indexPatternId = body[0];
- expect(body.length > 0).to.equal(true);
+ it('can create an index pattern', async () => {
+ const title = 'shakes*';
+ const fieldFormats = { bytes: { id: 'bytes' } };
+ const body = await (
+ await supertest
+ .post('/api/index-patterns-plugin/create')
+ .set('kbn-xsrf', 'anything')
+ .send({ title, fieldFormats })
+ .expect(200)
+ ).body;
+
+ indexPatternId = body.id;
+ expect(body.id).not.empty();
+ expect(body.title).to.equal(title);
+ expect(body.fields.length).to.equal(15);
+ expect(body.fieldFormatMap).to.eql(fieldFormats);
});
it('can get index pattern by id', async () => {
diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json
index 3b1e4faf80bce..2be68b797ba5f 100644
--- a/x-pack/.i18nrc.json
+++ b/x-pack/.i18nrc.json
@@ -28,7 +28,7 @@
"xpack.idxMgmt": "plugins/index_management",
"xpack.indexLifecycleMgmt": "plugins/index_lifecycle_management",
"xpack.infra": "plugins/infra",
- "xpack.fleet": "plugins/ingest_manager",
+ "xpack.fleet": "plugins/fleet",
"xpack.ingestPipelines": "plugins/ingest_pipelines",
"xpack.lens": "plugins/lens",
"xpack.licenseMgmt": "plugins/license_management",
diff --git a/x-pack/plugins/actions/README.md b/x-pack/plugins/actions/README.md
index 4fef9bc582d08..432a4bfff7a6b 100644
--- a/x-pack/plugins/actions/README.md
+++ b/x-pack/plugins/actions/README.md
@@ -69,18 +69,21 @@ Table of Contents
- [`secrets`](#secrets-6)
- [`params`](#params-6)
- [`subActionParams (pushToService)`](#subactionparams-pushtoservice)
+ - [`subActionParams (getFields)`](#subactionparams-getfields-1)
- [Jira](#jira)
- [`config`](#config-7)
- [`secrets`](#secrets-7)
- [`params`](#params-7)
- [`subActionParams (pushToService)`](#subactionparams-pushtoservice-1)
- [`subActionParams (issueTypes)`](#subactionparams-issuetypes)
+ - [`subActionParams (getFields)`](#subactionparams-getfields-2)
- [`subActionParams (pushToService)`](#subactionparams-pushtoservice-2)
- [IBM Resilient](#ibm-resilient)
- [`config`](#config-8)
- [`secrets`](#secrets-8)
- [`params`](#params-8)
- [`subActionParams (pushToService)`](#subactionparams-pushtoservice-3)
+ - [`subActionParams (getFields)`](#subactionparams-getfields-3)
- [Command Line Utility](#command-line-utility)
- [Developing New Action Types](#developing-new-action-types)
- [licensing](#licensing)
@@ -563,7 +566,7 @@ The ServiceNow action uses the [V2 Table API](https://developer.servicenow.com/a
| Property | Description | Type |
| --------------- | ------------------------------------------------------------------------------------ | ------ |
-| subAction | The sub action to perform. It can be `pushToService`, `handshake`, and `getIncident` | string |
+| subAction | The sub action to perform. It can be `getFields`, `pushToService`, `handshake`, and `getIncident` | string |
| subActionParams | The parameters of the sub action | object |
#### `subActionParams (pushToService)`
@@ -580,6 +583,10 @@ The ServiceNow action uses the [V2 Table API](https://developer.servicenow.com/a
| urgency | The name of the urgency in ServiceNow. | string _(optional)_ |
| impact | The name of the impact in ServiceNow. | string _(optional)_ |
+#### `subActionParams (getFields)`
+
+No parameters for `getFields` sub-action. Provide an empty object `{}`.
+
---
## Jira
@@ -606,7 +613,7 @@ The Jira action uses the [V2 API](https://developer.atlassian.com/cloud/jira/pla
| Property | Description | Type |
| --------------- | ----------------------------------------------------------------------------------------------------------------------- | ------ |
-| subAction | The sub action to perform. It can be `pushToService`, `handshake`, `getIncident`, `issueTypes`, and `fieldsByIssueType` | string |
+| subAction | The sub action to perform. It can be `getFields`, `pushToService`, `handshake`, `getIncident`, `issueTypes`, and `fieldsByIssueType` | string |
| subActionParams | The parameters of the sub action | object |
#### `subActionParams (pushToService)`
@@ -627,6 +634,10 @@ The Jira action uses the [V2 API](https://developer.atlassian.com/cloud/jira/pla
No parameters for `issueTypes` sub-action. Provide an empty object `{}`.
+#### `subActionParams (getFields)`
+
+No parameters for `getFields` sub-action. Provide an empty object `{}`.
+
#### `subActionParams (pushToService)`
| Property | Description | Type |
@@ -655,7 +666,7 @@ ID: `.resilient`
| Property | Description | Type |
| --------------- | ------------------------------------------------------------------------------------ | ------ |
-| subAction | The sub action to perform. It can be `pushToService`, `handshake`, and `getIncident` | string |
+| subAction | The sub action to perform. It can be `getFields`, `pushToService`, `handshake`, and `getIncident` | string |
| subActionParams | The parameters of the sub action | object |
#### `subActionParams (pushToService)`
@@ -670,6 +681,10 @@ ID: `.resilient`
| incidentTypes | An array with the ids of IBM Resilient incident types. | number[] _(optional)_ |
| severityCode | IBM Resilient id of the severity code. | number _(optional)_ |
+#### `subActionParams (getFields)`
+
+No parameters for `getFields` sub-action. Provide an empty object `{}`.
+
# Command Line Utility
The [`kbn-action`](https://github.com/pmuellr/kbn-action) tool can be used to send HTTP requests to the Actions plugin. For instance, to create a Slack action from the `.slack` Action Type, use the following command:
diff --git a/x-pack/plugins/actions/server/builtin_action_types/jira/api.test.ts b/x-pack/plugins/actions/server/builtin_action_types/jira/api.test.ts
index e8fa9f76df778..5a7617ada1bf0 100644
--- a/x-pack/plugins/actions/server/builtin_action_types/jira/api.test.ts
+++ b/x-pack/plugins/actions/server/builtin_action_types/jira/api.test.ts
@@ -15,804 +15,792 @@ describe('api', () => {
beforeEach(() => {
externalService = externalServiceMock.create();
- jest.clearAllMocks();
});
- afterEach(() => {
- jest.clearAllMocks();
- });
-
- describe('pushToService', () => {
- describe('create incident - cases', () => {
- test('it creates an incident', async () => {
- const params = { ...apiParams, externalId: null };
- const res = await api.pushToService({
- externalService,
- mapping,
- params,
- logger: mockedLogger,
- });
-
- expect(res).toEqual({
- id: 'incident-1',
- title: 'CK-1',
- pushedDate: '2020-04-27T10:59:46.202Z',
- url: 'https://siem-kibana.atlassian.net/browse/CK-1',
- comments: [
- {
- commentId: 'case-comment-1',
- pushedDate: '2020-04-27T10:59:46.202Z',
- },
- {
- commentId: 'case-comment-2',
- pushedDate: '2020-04-27T10:59:46.202Z',
- },
- ],
- });
- });
-
- test('it creates an incident without comments', async () => {
- const params = { ...apiParams, externalId: null, comments: [] };
- const res = await api.pushToService({
- externalService,
- mapping,
- params,
- logger: mockedLogger,
- });
-
- expect(res).toEqual({
- id: 'incident-1',
- title: 'CK-1',
- pushedDate: '2020-04-27T10:59:46.202Z',
- url: 'https://siem-kibana.atlassian.net/browse/CK-1',
- });
- });
-
- test('it calls createIncident correctly', async () => {
- const params = { ...apiParams, externalId: null };
- await api.pushToService({ externalService, mapping, params, logger: mockedLogger });
-
- expect(externalService.createIncident).toHaveBeenCalledWith({
- incident: {
- labels: ['kibana', 'elastic'],
- priority: 'High',
- issueType: '10006',
- parent: null,
- description:
- 'Incident description (created at 2020-04-27T10:59:46.202Z by Elastic User)',
- summary: 'Incident title (created at 2020-04-27T10:59:46.202Z by Elastic User)',
- },
- });
- expect(externalService.updateIncident).not.toHaveBeenCalled();
- });
-
- test('it calls createIncident correctly without mapping', async () => {
- const params = { ...apiParams, externalId: null };
- await api.pushToService({ externalService, mapping: null, params, logger: mockedLogger });
-
- expect(externalService.createIncident).toHaveBeenCalledWith({
- incident: {
- description: 'Incident description',
- summary: 'Incident title',
- issueType: '10006',
- labels: ['kibana', 'elastic'],
- priority: 'High',
- parent: null,
- },
- });
- expect(externalService.updateIncident).not.toHaveBeenCalled();
+ describe('create incident - cases', () => {
+ test('it creates an incident', async () => {
+ const params = { ...apiParams, externalId: null };
+ const res = await api.pushToService({
+ externalService,
+ mapping,
+ params,
+ logger: mockedLogger,
});
- test('it calls createComment correctly', async () => {
- const params = { ...apiParams, externalId: null };
- await api.pushToService({ externalService, mapping, params, logger: mockedLogger });
- expect(externalService.createComment).toHaveBeenCalledTimes(2);
- expect(externalService.createComment).toHaveBeenNthCalledWith(1, {
- incidentId: 'incident-1',
- comment: {
+ expect(res).toEqual({
+ id: 'incident-1',
+ title: 'CK-1',
+ pushedDate: '2020-04-27T10:59:46.202Z',
+ url: 'https://siem-kibana.atlassian.net/browse/CK-1',
+ comments: [
+ {
commentId: 'case-comment-1',
- comment: 'A comment (added at 2020-04-27T10:59:46.202Z by Elastic User)',
- createdAt: '2020-04-27T10:59:46.202Z',
- createdBy: {
- fullName: 'Elastic User',
- username: 'elastic',
- },
- updatedAt: '2020-04-27T10:59:46.202Z',
- updatedBy: {
- fullName: 'Elastic User',
- username: 'elastic',
- },
+ pushedDate: '2020-04-27T10:59:46.202Z',
},
- });
-
- expect(externalService.createComment).toHaveBeenNthCalledWith(2, {
- incidentId: 'incident-1',
- comment: {
+ {
commentId: 'case-comment-2',
- comment: 'Another comment (added at 2020-04-27T10:59:46.202Z by Elastic User)',
- createdAt: '2020-04-27T10:59:46.202Z',
- createdBy: {
- fullName: 'Elastic User',
- username: 'elastic',
- },
- updatedAt: '2020-04-27T10:59:46.202Z',
- updatedBy: {
- fullName: 'Elastic User',
- username: 'elastic',
- },
+ pushedDate: '2020-04-27T10:59:46.202Z',
},
- });
+ ],
});
+ });
- test('it calls createComment correctly without mapping', async () => {
- const params = { ...apiParams, externalId: null };
- await api.pushToService({ externalService, mapping: null, params, logger: mockedLogger });
- expect(externalService.createComment).toHaveBeenCalledTimes(2);
- expect(externalService.createComment).toHaveBeenNthCalledWith(1, {
- incidentId: 'incident-1',
- comment: {
- commentId: 'case-comment-1',
- comment: 'A comment',
- createdAt: '2020-04-27T10:59:46.202Z',
- createdBy: {
- fullName: 'Elastic User',
- username: 'elastic',
- },
- updatedAt: '2020-04-27T10:59:46.202Z',
- updatedBy: {
- fullName: 'Elastic User',
- username: 'elastic',
- },
- },
- });
+ test('it creates an incident without comments', async () => {
+ const params = { ...apiParams, externalId: null, comments: [] };
+ const res = await api.pushToService({
+ externalService,
+ mapping,
+ params,
+ logger: mockedLogger,
+ });
- expect(externalService.createComment).toHaveBeenNthCalledWith(2, {
- incidentId: 'incident-1',
- comment: {
- commentId: 'case-comment-2',
- comment: 'Another comment',
- createdAt: '2020-04-27T10:59:46.202Z',
- createdBy: {
- fullName: 'Elastic User',
- username: 'elastic',
- },
- updatedAt: '2020-04-27T10:59:46.202Z',
- updatedBy: {
- fullName: 'Elastic User',
- username: 'elastic',
- },
- },
- });
+ expect(res).toEqual({
+ id: 'incident-1',
+ title: 'CK-1',
+ pushedDate: '2020-04-27T10:59:46.202Z',
+ url: 'https://siem-kibana.atlassian.net/browse/CK-1',
});
});
- describe('update incident', () => {
- test('it updates an incident', async () => {
- const res = await api.pushToService({
- externalService,
- mapping,
- params: apiParams,
- logger: mockedLogger,
- });
-
- expect(res).toEqual({
- id: 'incident-1',
- title: 'CK-1',
- pushedDate: '2020-04-27T10:59:46.202Z',
- url: 'https://siem-kibana.atlassian.net/browse/CK-1',
- comments: [
- {
- commentId: 'case-comment-1',
- pushedDate: '2020-04-27T10:59:46.202Z',
- },
- {
- commentId: 'case-comment-2',
- pushedDate: '2020-04-27T10:59:46.202Z',
- },
- ],
- });
- });
-
- test('it updates an incident without comments', async () => {
- const params = { ...apiParams, comments: [] };
- const res = await api.pushToService({
- externalService,
- mapping,
- params,
- logger: mockedLogger,
- });
-
- expect(res).toEqual({
- id: 'incident-1',
- title: 'CK-1',
- pushedDate: '2020-04-27T10:59:46.202Z',
- url: 'https://siem-kibana.atlassian.net/browse/CK-1',
- });
- });
-
- test('it calls updateIncident correctly', async () => {
- const params = { ...apiParams };
- await api.pushToService({ externalService, mapping, params, logger: mockedLogger });
-
- expect(externalService.updateIncident).toHaveBeenCalledWith({
- incidentId: 'incident-3',
- incident: {
- labels: ['kibana', 'elastic'],
- priority: 'High',
- issueType: '10006',
- parent: null,
- description:
- 'Incident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
- summary: 'Incident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
+ test('it calls createIncident correctly', async () => {
+ const params = { ...apiParams, externalId: null };
+ await api.pushToService({ externalService, mapping, params, logger: mockedLogger });
+
+ expect(externalService.createIncident).toHaveBeenCalledWith({
+ incident: {
+ labels: ['kibana', 'elastic'],
+ priority: 'High',
+ issueType: '10006',
+ parent: null,
+ description: 'Incident description (created at 2020-04-27T10:59:46.202Z by Elastic User)',
+ summary: 'Incident title (created at 2020-04-27T10:59:46.202Z by Elastic User)',
+ },
+ });
+ expect(externalService.updateIncident).not.toHaveBeenCalled();
+ });
+
+ test('it calls createIncident correctly without mapping', async () => {
+ const params = { ...apiParams, externalId: null };
+ await api.pushToService({ externalService, mapping: null, params, logger: mockedLogger });
+
+ expect(externalService.createIncident).toHaveBeenCalledWith({
+ incident: {
+ description: 'Incident description',
+ summary: 'Incident title',
+ issueType: '10006',
+ labels: ['kibana', 'elastic'],
+ priority: 'High',
+ parent: null,
+ },
+ });
+ expect(externalService.updateIncident).not.toHaveBeenCalled();
+ });
+
+ test('it calls createComment correctly', async () => {
+ const params = { ...apiParams, externalId: null };
+ await api.pushToService({ externalService, mapping, params, logger: mockedLogger });
+ expect(externalService.createComment).toHaveBeenCalledTimes(2);
+ expect(externalService.createComment).toHaveBeenNthCalledWith(1, {
+ incidentId: 'incident-1',
+ comment: {
+ commentId: 'case-comment-1',
+ comment: 'A comment (added at 2020-04-27T10:59:46.202Z by Elastic User)',
+ createdAt: '2020-04-27T10:59:46.202Z',
+ createdBy: {
+ fullName: 'Elastic User',
+ username: 'elastic',
},
- });
- expect(externalService.createIncident).not.toHaveBeenCalled();
- });
-
- test('it calls updateIncident correctly without mapping', async () => {
- const params = { ...apiParams };
- await api.pushToService({ externalService, mapping: null, params, logger: mockedLogger });
-
- expect(externalService.updateIncident).toHaveBeenCalledWith({
- incidentId: 'incident-3',
- incident: {
- description: 'Incident description',
- summary: 'Incident title',
- issueType: '10006',
- labels: ['kibana', 'elastic'],
- priority: 'High',
- parent: null,
+ updatedAt: '2020-04-27T10:59:46.202Z',
+ updatedBy: {
+ fullName: 'Elastic User',
+ username: 'elastic',
},
- });
- expect(externalService.createIncident).not.toHaveBeenCalled();
+ },
});
- test('it calls createComment correctly', async () => {
- const params = { ...apiParams };
- await api.pushToService({ externalService, mapping, params, logger: mockedLogger });
- expect(externalService.createComment).toHaveBeenCalledTimes(2);
- expect(externalService.createComment).toHaveBeenNthCalledWith(1, {
- incidentId: 'incident-1',
- comment: {
- commentId: 'case-comment-1',
- comment: 'A comment (added at 2020-04-27T10:59:46.202Z by Elastic User)',
- createdAt: '2020-04-27T10:59:46.202Z',
- createdBy: {
- fullName: 'Elastic User',
- username: 'elastic',
- },
- updatedAt: '2020-04-27T10:59:46.202Z',
- updatedBy: {
- fullName: 'Elastic User',
- username: 'elastic',
- },
+ expect(externalService.createComment).toHaveBeenNthCalledWith(2, {
+ incidentId: 'incident-1',
+ comment: {
+ commentId: 'case-comment-2',
+ comment: 'Another comment (added at 2020-04-27T10:59:46.202Z by Elastic User)',
+ createdAt: '2020-04-27T10:59:46.202Z',
+ createdBy: {
+ fullName: 'Elastic User',
+ username: 'elastic',
},
- });
-
- expect(externalService.createComment).toHaveBeenNthCalledWith(2, {
- incidentId: 'incident-1',
- comment: {
- commentId: 'case-comment-2',
- comment: 'Another comment (added at 2020-04-27T10:59:46.202Z by Elastic User)',
- createdAt: '2020-04-27T10:59:46.202Z',
- createdBy: {
- fullName: 'Elastic User',
- username: 'elastic',
- },
- updatedAt: '2020-04-27T10:59:46.202Z',
- updatedBy: {
- fullName: 'Elastic User',
- username: 'elastic',
- },
+ updatedAt: '2020-04-27T10:59:46.202Z',
+ updatedBy: {
+ fullName: 'Elastic User',
+ username: 'elastic',
},
- });
+ },
});
+ });
- test('it calls createComment correctly without mapping', async () => {
- const params = { ...apiParams };
- await api.pushToService({ externalService, mapping: null, params, logger: mockedLogger });
- expect(externalService.createComment).toHaveBeenCalledTimes(2);
- expect(externalService.createComment).toHaveBeenNthCalledWith(1, {
- incidentId: 'incident-1',
- comment: {
- commentId: 'case-comment-1',
- comment: 'A comment',
- createdAt: '2020-04-27T10:59:46.202Z',
- createdBy: {
- fullName: 'Elastic User',
- username: 'elastic',
- },
- updatedAt: '2020-04-27T10:59:46.202Z',
- updatedBy: {
- fullName: 'Elastic User',
- username: 'elastic',
- },
+ test('it calls createComment correctly without mapping', async () => {
+ const params = { ...apiParams, externalId: null };
+ await api.pushToService({ externalService, mapping: null, params, logger: mockedLogger });
+ expect(externalService.createComment).toHaveBeenCalledTimes(2);
+ expect(externalService.createComment).toHaveBeenNthCalledWith(1, {
+ incidentId: 'incident-1',
+ comment: {
+ commentId: 'case-comment-1',
+ comment: 'A comment',
+ createdAt: '2020-04-27T10:59:46.202Z',
+ createdBy: {
+ fullName: 'Elastic User',
+ username: 'elastic',
+ },
+ updatedAt: '2020-04-27T10:59:46.202Z',
+ updatedBy: {
+ fullName: 'Elastic User',
+ username: 'elastic',
},
- });
+ },
+ });
- expect(externalService.createComment).toHaveBeenNthCalledWith(2, {
- incidentId: 'incident-1',
- comment: {
- commentId: 'case-comment-2',
- comment: 'Another comment',
- createdAt: '2020-04-27T10:59:46.202Z',
- createdBy: {
- fullName: 'Elastic User',
- username: 'elastic',
- },
- updatedAt: '2020-04-27T10:59:46.202Z',
- updatedBy: {
- fullName: 'Elastic User',
- username: 'elastic',
- },
+ expect(externalService.createComment).toHaveBeenNthCalledWith(2, {
+ incidentId: 'incident-1',
+ comment: {
+ commentId: 'case-comment-2',
+ comment: 'Another comment',
+ createdAt: '2020-04-27T10:59:46.202Z',
+ createdBy: {
+ fullName: 'Elastic User',
+ username: 'elastic',
+ },
+ updatedAt: '2020-04-27T10:59:46.202Z',
+ updatedBy: {
+ fullName: 'Elastic User',
+ username: 'elastic',
},
- });
+ },
});
});
+ });
- describe('issueTypes', () => {
- test('it returns the issue types correctly', async () => {
- const res = await api.issueTypes({
- externalService,
- params: {},
- });
- expect(res).toEqual([
+ describe('update incident', () => {
+ test('it updates an incident', async () => {
+ const res = await api.pushToService({
+ externalService,
+ mapping,
+ params: apiParams,
+ logger: mockedLogger,
+ });
+
+ expect(res).toEqual({
+ id: 'incident-1',
+ title: 'CK-1',
+ pushedDate: '2020-04-27T10:59:46.202Z',
+ url: 'https://siem-kibana.atlassian.net/browse/CK-1',
+ comments: [
{
- id: '10006',
- name: 'Task',
+ commentId: 'case-comment-1',
+ pushedDate: '2020-04-27T10:59:46.202Z',
},
{
- id: '10007',
- name: 'Bug',
+ commentId: 'case-comment-2',
+ pushedDate: '2020-04-27T10:59:46.202Z',
},
- ]);
+ ],
});
});
- describe('fieldsByIssueType', () => {
- test('it returns the fields correctly', async () => {
- const res = await api.fieldsByIssueType({
- externalService,
- params: { id: '10006' },
- });
- expect(res).toEqual({
- summary: { allowedValues: [], defaultValue: {} },
- priority: {
- allowedValues: [
- {
- name: 'Medium',
- id: '3',
- },
- ],
- defaultValue: { name: 'Medium', id: '3' },
- },
- });
+ test('it updates an incident without comments', async () => {
+ const params = { ...apiParams, comments: [] };
+ const res = await api.pushToService({
+ externalService,
+ mapping,
+ params,
+ logger: mockedLogger,
+ });
+
+ expect(res).toEqual({
+ id: 'incident-1',
+ title: 'CK-1',
+ pushedDate: '2020-04-27T10:59:46.202Z',
+ url: 'https://siem-kibana.atlassian.net/browse/CK-1',
});
});
- describe('getIssues', () => {
- test('it returns the issues correctly', async () => {
- const res = await api.issues({
- externalService,
- params: { title: 'Title test' },
- });
- expect(res).toEqual([
- {
- id: '10267',
- key: 'RJ-107',
- title: 'Test title',
- },
- ]);
+ test('it calls updateIncident correctly', async () => {
+ const params = { ...apiParams };
+ await api.pushToService({ externalService, mapping, params, logger: mockedLogger });
+
+ expect(externalService.updateIncident).toHaveBeenCalledWith({
+ incidentId: 'incident-3',
+ incident: {
+ labels: ['kibana', 'elastic'],
+ priority: 'High',
+ issueType: '10006',
+ parent: null,
+ description: 'Incident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
+ summary: 'Incident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
+ },
});
+ expect(externalService.createIncident).not.toHaveBeenCalled();
});
- describe('getIssue', () => {
- test('it returns the issue correctly', async () => {
- const res = await api.issue({
- externalService,
- params: { id: 'RJ-107' },
- });
- expect(res).toEqual({
- id: '10267',
- key: 'RJ-107',
- title: 'Test title',
- });
+ test('it calls updateIncident correctly without mapping', async () => {
+ const params = { ...apiParams };
+ await api.pushToService({ externalService, mapping: null, params, logger: mockedLogger });
+
+ expect(externalService.updateIncident).toHaveBeenCalledWith({
+ incidentId: 'incident-3',
+ incident: {
+ description: 'Incident description',
+ summary: 'Incident title',
+ issueType: '10006',
+ labels: ['kibana', 'elastic'],
+ priority: 'High',
+ parent: null,
+ },
});
+ expect(externalService.createIncident).not.toHaveBeenCalled();
});
- describe('mapping variations', () => {
- test('overwrite & append', async () => {
- mapping.set('title', {
- target: 'summary',
- actionType: 'overwrite',
- });
-
- mapping.set('description', {
- target: 'description',
- actionType: 'append',
- });
-
- mapping.set('comments', {
- target: 'comments',
- actionType: 'append',
- });
-
- mapping.set('summary', {
- target: 'title',
- actionType: 'overwrite',
- });
-
- await api.pushToService({
- externalService,
- mapping,
- params: apiParams,
- logger: mockedLogger,
- });
- expect(externalService.updateIncident).toHaveBeenCalledWith({
- incidentId: 'incident-3',
- incident: {
- labels: ['kibana', 'elastic'],
- priority: 'High',
- issueType: '10006',
- parent: null,
- summary: 'Incident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
- description:
- 'description from jira \r\nIncident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
- },
- });
- });
-
- test('nothing & append', async () => {
- mapping.set('title', {
- target: 'summary',
- actionType: 'nothing',
- });
-
- mapping.set('description', {
- target: 'description',
- actionType: 'append',
- });
-
- mapping.set('comments', {
- target: 'comments',
- actionType: 'append',
- });
-
- mapping.set('summary', {
- target: 'title',
- actionType: 'nothing',
- });
-
- await api.pushToService({
- externalService,
- mapping,
- params: apiParams,
- logger: mockedLogger,
- });
- expect(externalService.updateIncident).toHaveBeenCalledWith({
- incidentId: 'incident-3',
- incident: {
- labels: ['kibana', 'elastic'],
- priority: 'High',
- issueType: '10006',
- parent: null,
- description:
- 'description from jira \r\nIncident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
+ test('it calls createComment correctly', async () => {
+ const params = { ...apiParams };
+ await api.pushToService({ externalService, mapping, params, logger: mockedLogger });
+ expect(externalService.createComment).toHaveBeenCalledTimes(2);
+ expect(externalService.createComment).toHaveBeenNthCalledWith(1, {
+ incidentId: 'incident-1',
+ comment: {
+ commentId: 'case-comment-1',
+ comment: 'A comment (added at 2020-04-27T10:59:46.202Z by Elastic User)',
+ createdAt: '2020-04-27T10:59:46.202Z',
+ createdBy: {
+ fullName: 'Elastic User',
+ username: 'elastic',
},
- });
- });
-
- test('append & append', async () => {
- mapping.set('title', {
- target: 'summary',
- actionType: 'append',
- });
-
- mapping.set('description', {
- target: 'description',
- actionType: 'append',
- });
-
- mapping.set('comments', {
- target: 'comments',
- actionType: 'append',
- });
-
- mapping.set('summary', {
- target: 'title',
- actionType: 'append',
- });
-
- await api.pushToService({
- externalService,
- mapping,
- params: apiParams,
- logger: mockedLogger,
- });
- expect(externalService.updateIncident).toHaveBeenCalledWith({
- incidentId: 'incident-3',
- incident: {
- labels: ['kibana', 'elastic'],
- priority: 'High',
- issueType: '10006',
- parent: null,
- summary:
- 'title from jira \r\nIncident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
- description:
- 'description from jira \r\nIncident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
+ updatedAt: '2020-04-27T10:59:46.202Z',
+ updatedBy: {
+ fullName: 'Elastic User',
+ username: 'elastic',
},
- });
- });
-
- test('nothing & nothing', async () => {
- mapping.set('title', {
- target: 'summary',
- actionType: 'nothing',
- });
-
- mapping.set('description', {
- target: 'description',
- actionType: 'nothing',
- });
-
- mapping.set('comments', {
- target: 'comments',
- actionType: 'append',
- });
-
- mapping.set('summary', {
- target: 'title',
- actionType: 'nothing',
- });
-
- await api.pushToService({
- externalService,
- mapping,
- params: apiParams,
- logger: mockedLogger,
- });
- expect(externalService.updateIncident).toHaveBeenCalledWith({
- incidentId: 'incident-3',
- incident: {
- labels: ['kibana', 'elastic'],
- priority: 'High',
- issueType: '10006',
- parent: null,
+ },
+ });
+
+ expect(externalService.createComment).toHaveBeenNthCalledWith(2, {
+ incidentId: 'incident-1',
+ comment: {
+ commentId: 'case-comment-2',
+ comment: 'Another comment (added at 2020-04-27T10:59:46.202Z by Elastic User)',
+ createdAt: '2020-04-27T10:59:46.202Z',
+ createdBy: {
+ fullName: 'Elastic User',
+ username: 'elastic',
},
- });
- });
-
- test('overwrite & nothing', async () => {
- mapping.set('title', {
- target: 'summary',
- actionType: 'overwrite',
- });
-
- mapping.set('description', {
- target: 'description',
- actionType: 'nothing',
- });
-
- mapping.set('comments', {
- target: 'comments',
- actionType: 'append',
- });
-
- mapping.set('summary', {
- target: 'title',
- actionType: 'overwrite',
- });
-
- await api.pushToService({
- externalService,
- mapping,
- params: apiParams,
- logger: mockedLogger,
- });
- expect(externalService.updateIncident).toHaveBeenCalledWith({
- incidentId: 'incident-3',
- incident: {
- labels: ['kibana', 'elastic'],
- priority: 'High',
- issueType: '10006',
- parent: null,
- summary: 'Incident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
+ updatedAt: '2020-04-27T10:59:46.202Z',
+ updatedBy: {
+ fullName: 'Elastic User',
+ username: 'elastic',
},
- });
- });
-
- test('overwrite & overwrite', async () => {
- mapping.set('title', {
- target: 'summary',
- actionType: 'overwrite',
- });
-
- mapping.set('description', {
- target: 'description',
- actionType: 'overwrite',
- });
-
- mapping.set('comments', {
- target: 'comments',
- actionType: 'append',
- });
-
- mapping.set('summary', {
- target: 'title',
- actionType: 'overwrite',
- });
-
- await api.pushToService({
- externalService,
- mapping,
- params: apiParams,
- logger: mockedLogger,
- });
- expect(externalService.updateIncident).toHaveBeenCalledWith({
- incidentId: 'incident-3',
- incident: {
- labels: ['kibana', 'elastic'],
- priority: 'High',
- issueType: '10006',
- parent: null,
- summary: 'Incident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
- description:
- 'Incident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
+ },
+ });
+ });
+
+ test('it calls createComment correctly without mapping', async () => {
+ const params = { ...apiParams };
+ await api.pushToService({ externalService, mapping: null, params, logger: mockedLogger });
+ expect(externalService.createComment).toHaveBeenCalledTimes(2);
+ expect(externalService.createComment).toHaveBeenNthCalledWith(1, {
+ incidentId: 'incident-1',
+ comment: {
+ commentId: 'case-comment-1',
+ comment: 'A comment',
+ createdAt: '2020-04-27T10:59:46.202Z',
+ createdBy: {
+ fullName: 'Elastic User',
+ username: 'elastic',
},
- });
- });
-
- test('nothing & overwrite', async () => {
- mapping.set('title', {
- target: 'summary',
- actionType: 'nothing',
- });
-
- mapping.set('description', {
- target: 'description',
- actionType: 'overwrite',
- });
-
- mapping.set('comments', {
- target: 'comments',
- actionType: 'append',
- });
-
- mapping.set('summary', {
- target: 'title',
- actionType: 'nothing',
- });
-
- await api.pushToService({
- externalService,
- mapping,
- params: apiParams,
- logger: mockedLogger,
- });
- expect(externalService.updateIncident).toHaveBeenCalledWith({
- incidentId: 'incident-3',
- incident: {
- labels: ['kibana', 'elastic'],
- priority: 'High',
- issueType: '10006',
- parent: null,
- description:
- 'Incident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
+ updatedAt: '2020-04-27T10:59:46.202Z',
+ updatedBy: {
+ fullName: 'Elastic User',
+ username: 'elastic',
},
- });
- });
-
- test('append & overwrite', async () => {
- mapping.set('title', {
- target: 'summary',
- actionType: 'append',
- });
-
- mapping.set('description', {
- target: 'description',
- actionType: 'overwrite',
- });
-
- mapping.set('comments', {
- target: 'comments',
- actionType: 'append',
- });
-
- mapping.set('summary', {
- target: 'title',
- actionType: 'append',
- });
-
- await api.pushToService({
- externalService,
- mapping,
- params: apiParams,
- logger: mockedLogger,
- });
- expect(externalService.updateIncident).toHaveBeenCalledWith({
- incidentId: 'incident-3',
- incident: {
- labels: ['kibana', 'elastic'],
- priority: 'High',
- issueType: '10006',
- parent: null,
- summary:
- 'title from jira \r\nIncident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
- description:
- 'Incident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
+ },
+ });
+
+ expect(externalService.createComment).toHaveBeenNthCalledWith(2, {
+ incidentId: 'incident-1',
+ comment: {
+ commentId: 'case-comment-2',
+ comment: 'Another comment',
+ createdAt: '2020-04-27T10:59:46.202Z',
+ createdBy: {
+ fullName: 'Elastic User',
+ username: 'elastic',
},
- });
- });
-
- test('append & nothing', async () => {
- mapping.set('title', {
- target: 'summary',
- actionType: 'append',
- });
-
- mapping.set('description', {
- target: 'description',
- actionType: 'nothing',
- });
-
- mapping.set('comments', {
- target: 'comments',
- actionType: 'append',
- });
-
- mapping.set('summary', {
- target: 'title',
- actionType: 'append',
- });
-
- await api.pushToService({
- externalService,
- mapping,
- params: apiParams,
- logger: mockedLogger,
- });
- expect(externalService.updateIncident).toHaveBeenCalledWith({
- incidentId: 'incident-3',
- incident: {
- labels: ['kibana', 'elastic'],
- priority: 'High',
- issueType: '10006',
- parent: null,
- summary:
- 'title from jira \r\nIncident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
+ updatedAt: '2020-04-27T10:59:46.202Z',
+ updatedBy: {
+ fullName: 'Elastic User',
+ username: 'elastic',
},
- });
- });
-
- test('comment nothing', async () => {
- mapping.set('title', {
- target: 'summary',
- actionType: 'overwrite',
- });
-
- mapping.set('description', {
- target: 'description',
- actionType: 'nothing',
- });
-
- mapping.set('comments', {
- target: 'comments',
- actionType: 'nothing',
- });
-
- mapping.set('summary', {
- target: 'title',
- actionType: 'overwrite',
- });
-
- await api.pushToService({
- externalService,
- mapping,
- params: apiParams,
- logger: mockedLogger,
- });
- expect(externalService.createComment).not.toHaveBeenCalled();
+ },
+ });
+ });
+ });
+
+ describe('issueTypes', () => {
+ test('it returns the issue types correctly', async () => {
+ const res = await api.issueTypes({
+ externalService,
+ params: {},
+ });
+ expect(res).toEqual([
+ {
+ id: '10006',
+ name: 'Task',
+ },
+ {
+ id: '10007',
+ name: 'Bug',
+ },
+ ]);
+ });
+ });
+
+ describe('fieldsByIssueType', () => {
+ test('it returns the fields correctly', async () => {
+ const res = await api.fieldsByIssueType({
+ externalService,
+ params: { id: '10006' },
+ });
+ expect(res).toEqual({
+ summary: { allowedValues: [], defaultValue: {} },
+ priority: {
+ allowedValues: [
+ {
+ name: 'Medium',
+ id: '3',
+ },
+ ],
+ defaultValue: { name: 'Medium', id: '3' },
+ },
+ });
+ });
+ });
+
+ describe('getIssues', () => {
+ test('it returns the issues correctly', async () => {
+ const res = await api.issues({
+ externalService,
+ params: { title: 'Title test' },
+ });
+ expect(res).toEqual([
+ {
+ id: '10267',
+ key: 'RJ-107',
+ title: 'Test title',
+ },
+ ]);
+ });
+ });
+
+ describe('getIssue', () => {
+ test('it returns the issue correctly', async () => {
+ const res = await api.issue({
+ externalService,
+ params: { id: 'RJ-107' },
+ });
+ expect(res).toEqual({
+ id: '10267',
+ key: 'RJ-107',
+ title: 'Test title',
+ });
+ });
+ });
+
+ describe('mapping variations', () => {
+ test('overwrite & append', async () => {
+ mapping.set('title', {
+ target: 'summary',
+ actionType: 'overwrite',
+ });
+
+ mapping.set('description', {
+ target: 'description',
+ actionType: 'append',
+ });
+
+ mapping.set('comments', {
+ target: 'comments',
+ actionType: 'append',
+ });
+
+ mapping.set('summary', {
+ target: 'title',
+ actionType: 'overwrite',
+ });
+
+ await api.pushToService({
+ externalService,
+ mapping,
+ params: apiParams,
+ logger: mockedLogger,
+ });
+ expect(externalService.updateIncident).toHaveBeenCalledWith({
+ incidentId: 'incident-3',
+ incident: {
+ labels: ['kibana', 'elastic'],
+ priority: 'High',
+ issueType: '10006',
+ parent: null,
+ summary: 'Incident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
+ description:
+ 'description from jira \r\nIncident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
+ },
+ });
+ });
+
+ test('nothing & append', async () => {
+ mapping.set('title', {
+ target: 'summary',
+ actionType: 'nothing',
+ });
+
+ mapping.set('description', {
+ target: 'description',
+ actionType: 'append',
+ });
+
+ mapping.set('comments', {
+ target: 'comments',
+ actionType: 'append',
+ });
+
+ mapping.set('summary', {
+ target: 'title',
+ actionType: 'nothing',
+ });
+
+ await api.pushToService({
+ externalService,
+ mapping,
+ params: apiParams,
+ logger: mockedLogger,
+ });
+ expect(externalService.updateIncident).toHaveBeenCalledWith({
+ incidentId: 'incident-3',
+ incident: {
+ labels: ['kibana', 'elastic'],
+ priority: 'High',
+ issueType: '10006',
+ parent: null,
+ description:
+ 'description from jira \r\nIncident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
+ },
+ });
+ });
+
+ test('append & append', async () => {
+ mapping.set('title', {
+ target: 'summary',
+ actionType: 'append',
+ });
+
+ mapping.set('description', {
+ target: 'description',
+ actionType: 'append',
+ });
+
+ mapping.set('comments', {
+ target: 'comments',
+ actionType: 'append',
+ });
+
+ mapping.set('summary', {
+ target: 'title',
+ actionType: 'append',
+ });
+
+ await api.pushToService({
+ externalService,
+ mapping,
+ params: apiParams,
+ logger: mockedLogger,
+ });
+ expect(externalService.updateIncident).toHaveBeenCalledWith({
+ incidentId: 'incident-3',
+ incident: {
+ labels: ['kibana', 'elastic'],
+ priority: 'High',
+ issueType: '10006',
+ parent: null,
+ summary:
+ 'title from jira \r\nIncident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
+ description:
+ 'description from jira \r\nIncident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
+ },
+ });
+ });
+
+ test('nothing & nothing', async () => {
+ mapping.set('title', {
+ target: 'summary',
+ actionType: 'nothing',
+ });
+
+ mapping.set('description', {
+ target: 'description',
+ actionType: 'nothing',
+ });
+
+ mapping.set('comments', {
+ target: 'comments',
+ actionType: 'append',
+ });
+
+ mapping.set('summary', {
+ target: 'title',
+ actionType: 'nothing',
+ });
+
+ await api.pushToService({
+ externalService,
+ mapping,
+ params: apiParams,
+ logger: mockedLogger,
+ });
+ expect(externalService.updateIncident).toHaveBeenCalledWith({
+ incidentId: 'incident-3',
+ incident: {
+ labels: ['kibana', 'elastic'],
+ priority: 'High',
+ issueType: '10006',
+ parent: null,
+ },
+ });
+ });
+
+ test('overwrite & nothing', async () => {
+ mapping.set('title', {
+ target: 'summary',
+ actionType: 'overwrite',
+ });
+
+ mapping.set('description', {
+ target: 'description',
+ actionType: 'nothing',
+ });
+
+ mapping.set('comments', {
+ target: 'comments',
+ actionType: 'append',
+ });
+
+ mapping.set('summary', {
+ target: 'title',
+ actionType: 'overwrite',
+ });
+
+ await api.pushToService({
+ externalService,
+ mapping,
+ params: apiParams,
+ logger: mockedLogger,
+ });
+ expect(externalService.updateIncident).toHaveBeenCalledWith({
+ incidentId: 'incident-3',
+ incident: {
+ labels: ['kibana', 'elastic'],
+ priority: 'High',
+ issueType: '10006',
+ parent: null,
+ summary: 'Incident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
+ },
+ });
+ });
+
+ test('overwrite & overwrite', async () => {
+ mapping.set('title', {
+ target: 'summary',
+ actionType: 'overwrite',
+ });
+
+ mapping.set('description', {
+ target: 'description',
+ actionType: 'overwrite',
+ });
+
+ mapping.set('comments', {
+ target: 'comments',
+ actionType: 'append',
+ });
+
+ mapping.set('summary', {
+ target: 'title',
+ actionType: 'overwrite',
+ });
+
+ await api.pushToService({
+ externalService,
+ mapping,
+ params: apiParams,
+ logger: mockedLogger,
+ });
+ expect(externalService.updateIncident).toHaveBeenCalledWith({
+ incidentId: 'incident-3',
+ incident: {
+ labels: ['kibana', 'elastic'],
+ priority: 'High',
+ issueType: '10006',
+ parent: null,
+ summary: 'Incident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
+ description: 'Incident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
+ },
+ });
+ });
+
+ test('nothing & overwrite', async () => {
+ mapping.set('title', {
+ target: 'summary',
+ actionType: 'nothing',
+ });
+
+ mapping.set('description', {
+ target: 'description',
+ actionType: 'overwrite',
+ });
+
+ mapping.set('comments', {
+ target: 'comments',
+ actionType: 'append',
+ });
+
+ mapping.set('summary', {
+ target: 'title',
+ actionType: 'nothing',
+ });
+
+ await api.pushToService({
+ externalService,
+ mapping,
+ params: apiParams,
+ logger: mockedLogger,
+ });
+ expect(externalService.updateIncident).toHaveBeenCalledWith({
+ incidentId: 'incident-3',
+ incident: {
+ labels: ['kibana', 'elastic'],
+ priority: 'High',
+ issueType: '10006',
+ parent: null,
+ description: 'Incident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
+ },
+ });
+ });
+
+ test('append & overwrite', async () => {
+ mapping.set('title', {
+ target: 'summary',
+ actionType: 'append',
+ });
+
+ mapping.set('description', {
+ target: 'description',
+ actionType: 'overwrite',
+ });
+
+ mapping.set('comments', {
+ target: 'comments',
+ actionType: 'append',
+ });
+
+ mapping.set('summary', {
+ target: 'title',
+ actionType: 'append',
+ });
+
+ await api.pushToService({
+ externalService,
+ mapping,
+ params: apiParams,
+ logger: mockedLogger,
+ });
+ expect(externalService.updateIncident).toHaveBeenCalledWith({
+ incidentId: 'incident-3',
+ incident: {
+ labels: ['kibana', 'elastic'],
+ priority: 'High',
+ issueType: '10006',
+ parent: null,
+ summary:
+ 'title from jira \r\nIncident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
+ description: 'Incident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
+ },
+ });
+ });
+
+ test('append & nothing', async () => {
+ mapping.set('title', {
+ target: 'summary',
+ actionType: 'append',
+ });
+
+ mapping.set('description', {
+ target: 'description',
+ actionType: 'nothing',
+ });
+
+ mapping.set('comments', {
+ target: 'comments',
+ actionType: 'append',
+ });
+
+ mapping.set('summary', {
+ target: 'title',
+ actionType: 'append',
+ });
+
+ await api.pushToService({
+ externalService,
+ mapping,
+ params: apiParams,
+ logger: mockedLogger,
+ });
+ expect(externalService.updateIncident).toHaveBeenCalledWith({
+ incidentId: 'incident-3',
+ incident: {
+ labels: ['kibana', 'elastic'],
+ priority: 'High',
+ issueType: '10006',
+ parent: null,
+ summary:
+ 'title from jira \r\nIncident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)',
+ },
+ });
+ });
+
+ test('comment nothing', async () => {
+ mapping.set('title', {
+ target: 'summary',
+ actionType: 'overwrite',
+ });
+
+ mapping.set('description', {
+ target: 'description',
+ actionType: 'nothing',
+ });
+
+ mapping.set('comments', {
+ target: 'comments',
+ actionType: 'nothing',
+ });
+
+ mapping.set('summary', {
+ target: 'title',
+ actionType: 'overwrite',
+ });
+
+ await api.pushToService({
+ externalService,
+ mapping,
+ params: apiParams,
+ logger: mockedLogger,
});
+ expect(externalService.createComment).not.toHaveBeenCalled();
});
});
});
diff --git a/x-pack/plugins/actions/server/builtin_action_types/jira/api.ts b/x-pack/plugins/actions/server/builtin_action_types/jira/api.ts
index 679c1541964ce..feeb69b1d1a0e 100644
--- a/x-pack/plugins/actions/server/builtin_action_types/jira/api.ts
+++ b/x-pack/plugins/actions/server/builtin_action_types/jira/api.ts
@@ -17,6 +17,7 @@ import {
PushToServiceApiParams,
PushToServiceResponse,
GetIssueHandlerArgs,
+ GetCommonFieldsHandlerArgs,
} from './types';
// TODO: to remove, need to support Case
@@ -39,6 +40,11 @@ const getIssueTypesHandler = async ({ externalService }: GetIssueTypesHandlerArg
return res;
};
+const getFieldsHandler = async ({ externalService }: GetCommonFieldsHandlerArgs) => {
+ const res = await externalService.getFields();
+ return res;
+};
+
const getFieldsByIssueTypeHandler = async ({
externalService,
params,
@@ -157,6 +163,7 @@ const pushToServiceHandler = async ({
};
export const api: ExternalServiceApi = {
+ getFields: getFieldsHandler,
handshake: handshakeHandler,
pushToService: pushToServiceHandler,
getIncident: getIncidentHandler,
diff --git a/x-pack/plugins/actions/server/builtin_action_types/jira/index.ts b/x-pack/plugins/actions/server/builtin_action_types/jira/index.ts
index 9d6ff90c33700..c70c0810926f4 100644
--- a/x-pack/plugins/actions/server/builtin_action_types/jira/index.ts
+++ b/x-pack/plugins/actions/server/builtin_action_types/jira/index.ts
@@ -40,6 +40,7 @@ interface GetActionTypeParams {
}
const supportedSubActions: string[] = [
+ 'getFields',
'pushToService',
'issueTypes',
'fieldsByIssueType',
@@ -145,6 +146,13 @@ async function executor(
});
}
+ if (subAction === 'getFields') {
+ data = await api.getFields({
+ externalService,
+ params: subActionParams,
+ });
+ }
+
if (subAction === 'issues') {
const getIssuesParams = subActionParams as ExecutorSubActionGetIssuesParams;
data = await api.issues({
diff --git a/x-pack/plugins/actions/server/builtin_action_types/jira/mocks.ts b/x-pack/plugins/actions/server/builtin_action_types/jira/mocks.ts
index b98eda799e3aa..87a0f156a0c2a 100644
--- a/x-pack/plugins/actions/server/builtin_action_types/jira/mocks.ts
+++ b/x-pack/plugins/actions/server/builtin_action_types/jira/mocks.ts
@@ -73,6 +73,20 @@ const createMock = (): jest.Mocked => {
key: 'RJ-107',
title: 'Test title',
})),
+ getFields: jest.fn().mockImplementation(() => ({
+ description: {
+ allowedValues: [],
+ defaultValue: {},
+ required: true,
+ schema: { type: 'string' },
+ },
+ summary: {
+ allowedValues: [],
+ defaultValue: {},
+ required: true,
+ schema: { type: 'string' },
+ },
+ })),
};
service.createComment.mockImplementationOnce(() =>
@@ -97,7 +111,6 @@ const createMock = (): jest.Mocked => {
const externalServiceMock = {
create: createMock,
};
-
const mapping: Map> = new Map();
mapping.set('title', {
diff --git a/x-pack/plugins/actions/server/builtin_action_types/jira/schema.ts b/x-pack/plugins/actions/server/builtin_action_types/jira/schema.ts
index 513ca2cf18e6c..70b60ada9c386 100644
--- a/x-pack/plugins/actions/server/builtin_action_types/jira/schema.ts
+++ b/x-pack/plugins/actions/server/builtin_action_types/jira/schema.ts
@@ -55,6 +55,7 @@ export const ExecutorSubActionGetIncidentParamsSchema = schema.object({
});
// Reserved for future implementation
+export const ExecutorSubActionCommonFieldsParamsSchema = schema.object({});
export const ExecutorSubActionHandshakeParamsSchema = schema.object({});
export const ExecutorSubActionGetCapabilitiesParamsSchema = schema.object({});
export const ExecutorSubActionGetIssueTypesParamsSchema = schema.object({});
@@ -65,6 +66,10 @@ export const ExecutorSubActionGetIssuesParamsSchema = schema.object({ title: sch
export const ExecutorSubActionGetIssueParamsSchema = schema.object({ id: schema.string() });
export const ExecutorParamsSchema = schema.oneOf([
+ schema.object({
+ subAction: schema.literal('getFields'),
+ subActionParams: ExecutorSubActionCommonFieldsParamsSchema,
+ }),
schema.object({
subAction: schema.literal('getIncident'),
subActionParams: ExecutorSubActionGetIncidentParamsSchema,
diff --git a/x-pack/plugins/actions/server/builtin_action_types/jira/service.test.ts b/x-pack/plugins/actions/server/builtin_action_types/jira/service.test.ts
index fe4e135c76fc3..2165ba56428c9 100644
--- a/x-pack/plugins/actions/server/builtin_action_types/jira/service.test.ts
+++ b/x-pack/plugins/actions/server/builtin_action_types/jira/service.test.ts
@@ -57,8 +57,10 @@ const fieldsResponse = {
id: '10006',
name: 'Task',
fields: {
- summary: { fieldId: 'summary' },
+ summary: { required: true, schema: { type: 'string' }, fieldId: 'summary' },
priority: {
+ required: false,
+ schema: { type: 'string' },
fieldId: 'priority',
allowedValues: [
{
@@ -198,7 +200,7 @@ describe('Jira service', () => {
error.response = { data: { errors: { summary: 'Required field' } } };
throw error;
});
- expect(service.getIncident('1')).rejects.toThrow(
+ await expect(service.getIncident('1')).rejects.toThrow(
'[Action][Jira]: Unable to get incident with id 1. Error: An error has occurred Reason: Required field'
);
});
@@ -348,7 +350,7 @@ describe('Jira service', () => {
throw error;
});
- expect(
+ await expect(
service.createIncident({
incident: {
summary: 'title',
@@ -442,7 +444,7 @@ describe('Jira service', () => {
throw error;
});
- expect(
+ await expect(
service.updateIncident({
incidentId: '1',
incident: {
@@ -526,7 +528,7 @@ describe('Jira service', () => {
throw error;
});
- expect(
+ await expect(
service.createComment({
incidentId: '1',
comment: {
@@ -587,7 +589,7 @@ describe('Jira service', () => {
throw error;
});
- expect(service.getCapabilities()).rejects.toThrow(
+ await expect(service.getCapabilities()).rejects.toThrow(
'[Action][Jira]: Unable to get capabilities. Error: An error has occurred. Reason: Could not get capabilities'
);
});
@@ -657,7 +659,7 @@ describe('Jira service', () => {
throw error;
});
- expect(service.getIssueTypes()).rejects.toThrow(
+ await expect(service.getIssueTypes()).rejects.toThrow(
'[Action][Jira]: Unable to get issue types. Error: An error has occurred. Reason: Could not get issue types'
);
});
@@ -741,7 +743,7 @@ describe('Jira service', () => {
throw error;
});
- expect(service.getIssueTypes()).rejects.toThrow(
+ await expect(service.getIssueTypes()).rejects.toThrow(
'[Action][Jira]: Unable to get issue types. Error: An error has occurred. Reason: Could not get issue types'
);
});
@@ -765,6 +767,8 @@ describe('Jira service', () => {
expect(res).toEqual({
priority: {
+ required: false,
+ schema: { type: 'string' },
allowedValues: [
{ id: '1', name: 'Highest' },
{ id: '2', name: 'High' },
@@ -774,7 +778,12 @@ describe('Jira service', () => {
],
defaultValue: { id: '3', name: 'Medium' },
},
- summary: { allowedValues: [], defaultValue: {} },
+ summary: {
+ required: true,
+ schema: { type: 'string' },
+ allowedValues: [],
+ defaultValue: {},
+ },
});
});
@@ -815,7 +824,7 @@ describe('Jira service', () => {
throw error;
});
- expect(service.getFieldsByIssueType('10006')).rejects.toThrow(
+ await expect(service.getFieldsByIssueType('10006')).rejects.toThrow(
'[Action][Jira]: Unable to get fields. Error: An error has occurred. Reason: Could not get fields'
);
});
@@ -837,8 +846,10 @@ describe('Jira service', () => {
requestMock.mockImplementationOnce(() => ({
data: {
values: [
- { fieldId: 'summary' },
+ { required: true, schema: { type: 'string' }, fieldId: 'summary' },
{
+ required: false,
+ schema: { type: 'string' },
fieldId: 'priority',
allowedValues: [
{
@@ -859,10 +870,17 @@ describe('Jira service', () => {
expect(res).toEqual({
priority: {
+ required: false,
+ schema: { type: 'string' },
allowedValues: [{ id: '3', name: 'Medium' }],
defaultValue: { id: '3', name: 'Medium' },
},
- summary: { allowedValues: [], defaultValue: {} },
+ summary: {
+ required: true,
+ schema: { type: 'string' },
+ allowedValues: [],
+ defaultValue: {},
+ },
});
});
@@ -881,8 +899,10 @@ describe('Jira service', () => {
requestMock.mockImplementationOnce(() => ({
data: {
values: [
- { fieldId: 'summary' },
+ { required: true, schema: { type: 'string' }, fieldId: 'summary' },
{
+ required: true,
+ schema: { type: 'string' },
fieldId: 'priority',
allowedValues: [
{
@@ -927,7 +947,7 @@ describe('Jira service', () => {
throw error;
});
- expect(service.getFieldsByIssueType('10006')).rejects.toThrow(
+ await expect(service.getFieldsByIssueType('10006')).rejects.toThrowError(
'[Action][Jira]: Unable to get fields. Error: An error has occurred. Reason: Could not get issue types'
);
});
@@ -976,7 +996,7 @@ describe('Jira service', () => {
throw error;
});
- expect(service.getIssues('Test title')).rejects.toThrow(
+ await expect(service.getIssues('Test title')).rejects.toThrow(
'[Action][Jira]: Unable to get issues. Error: An error has occurred. Reason: Could not get issue types'
);
});
@@ -1020,9 +1040,128 @@ describe('Jira service', () => {
throw error;
});
- expect(service.getIssue('RJ-107')).rejects.toThrow(
+ await expect(service.getIssue('RJ-107')).rejects.toThrow(
'[Action][Jira]: Unable to get issue with id RJ-107. Error: An error has occurred. Reason: Could not get issue types'
);
});
});
+
+ describe('getFields', () => {
+ const callMocks = () => {
+ requestMock
+ .mockImplementationOnce(() => ({
+ data: {
+ capabilities: {
+ 'list-project-issuetypes':
+ 'https://siem-kibana.atlassian.net/rest/capabilities/list-project-issuetypes',
+ 'list-issuetype-fields':
+ 'https://siem-kibana.atlassian.net/rest/capabilities/list-issuetype-fields',
+ },
+ },
+ }))
+ .mockImplementationOnce(() => ({
+ data: {
+ values: issueTypesResponse.data.projects[0].issuetypes,
+ },
+ }))
+ .mockImplementationOnce(() => ({
+ data: {
+ capabilities: {
+ 'list-project-issuetypes':
+ 'https://siem-kibana.atlassian.net/rest/capabilities/list-project-issuetypes',
+ 'list-issuetype-fields':
+ 'https://siem-kibana.atlassian.net/rest/capabilities/list-issuetype-fields',
+ },
+ },
+ }))
+ .mockImplementationOnce(() => ({
+ data: {
+ capabilities: {
+ 'list-project-issuetypes':
+ 'https://siem-kibana.atlassian.net/rest/capabilities/list-project-issuetypes',
+ 'list-issuetype-fields':
+ 'https://siem-kibana.atlassian.net/rest/capabilities/list-issuetype-fields',
+ },
+ },
+ }))
+ .mockImplementationOnce(() => ({
+ data: {
+ values: [
+ { required: true, schema: { type: 'string' }, fieldId: 'summary' },
+ { required: true, schema: { type: 'string' }, fieldId: 'description' },
+ {
+ required: false,
+ schema: { type: 'string' },
+ fieldId: 'priority',
+ allowedValues: [
+ {
+ name: 'Medium',
+ id: '3',
+ },
+ ],
+ defaultValue: {
+ name: 'Medium',
+ id: '3',
+ },
+ },
+ ],
+ },
+ }))
+ .mockImplementationOnce(() => ({
+ data: {
+ values: [
+ { required: true, schema: { type: 'string' }, fieldId: 'summary' },
+ { required: true, schema: { type: 'string' }, fieldId: 'description' },
+ ],
+ },
+ }));
+ };
+ beforeEach(() => {
+ jest.resetAllMocks();
+ });
+ test('it should call request with correct arguments', async () => {
+ callMocks();
+ await service.getFields();
+ const callUrls = [
+ 'https://siem-kibana.atlassian.net/rest/capabilities',
+ 'https://siem-kibana.atlassian.net/rest/api/2/issue/createmeta/CK/issuetypes',
+ 'https://siem-kibana.atlassian.net/rest/capabilities',
+ 'https://siem-kibana.atlassian.net/rest/capabilities',
+ 'https://siem-kibana.atlassian.net/rest/api/2/issue/createmeta/CK/issuetypes/10006',
+ 'https://siem-kibana.atlassian.net/rest/api/2/issue/createmeta/CK/issuetypes/10007',
+ ];
+ requestMock.mock.calls.forEach((call, i) => {
+ expect(call[0].url).toEqual(callUrls[i]);
+ });
+ });
+ test('it returns common fields correctly', async () => {
+ callMocks();
+ const res = await service.getFields();
+ expect(res).toEqual({
+ description: {
+ allowedValues: [],
+ defaultValue: {},
+ required: true,
+ schema: { type: 'string' },
+ },
+ summary: {
+ allowedValues: [],
+ defaultValue: {},
+ required: true,
+ schema: { type: 'string' },
+ },
+ });
+ });
+
+ test('it should throw an error', async () => {
+ requestMock.mockImplementation(() => {
+ const error: ResponseError = new Error('An error has occurred');
+ error.response = { data: { errors: { summary: 'Required field' } } };
+ throw error;
+ });
+ await expect(service.getFields()).rejects.toThrow(
+ '[Action][Jira]: Unable to get capabilities. Error: An error has occurred. Reason: Required field'
+ );
+ });
+ });
});
diff --git a/x-pack/plugins/actions/server/builtin_action_types/jira/service.ts b/x-pack/plugins/actions/server/builtin_action_types/jira/service.ts
index f5347891f4f70..b3c5bb4a84de5 100644
--- a/x-pack/plugins/actions/server/builtin_action_types/jira/service.ts
+++ b/x-pack/plugins/actions/server/builtin_action_types/jira/service.ts
@@ -8,18 +8,20 @@ import axios from 'axios';
import { Logger } from '../../../../../../src/core/server';
import {
- ExternalServiceCredentials,
- ExternalService,
+ CreateCommentParams,
CreateIncidentParams,
- UpdateIncidentParams,
- JiraPublicConfigurationType,
- JiraSecretConfigurationType,
+ ExternalService,
+ ExternalServiceCommentResponse,
+ ExternalServiceCredentials,
+ ExternalServiceIncidentResponse,
Fields,
- CreateCommentParams,
+ FieldSchema,
+ GetCommonFieldsResponse,
Incident,
+ JiraPublicConfigurationType,
+ JiraSecretConfigurationType,
ResponseError,
- ExternalServiceCommentResponse,
- ExternalServiceIncidentResponse,
+ UpdateIncidentParams,
} from './types';
import * as i18n from './translations';
@@ -127,14 +129,21 @@ export const createExternalService = (
issueTypes.map((type) => ({ id: type.id, name: type.name }));
const normalizeFields = (fields: {
- [key: string]: { allowedValues?: Array<{}>; defaultValue?: {} };
+ [key: string]: {
+ allowedValues?: Array<{}>;
+ defaultValue?: {};
+ required: boolean;
+ schema: FieldSchema;
+ };
}) =>
Object.keys(fields ?? {}).reduce((fieldsAcc, fieldKey) => {
return {
...fieldsAcc,
[fieldKey]: {
+ required: fields[fieldKey]?.required,
allowedValues: fields[fieldKey]?.allowedValues ?? [],
defaultValue: fields[fieldKey]?.defaultValue ?? {},
+ schema: fields[fieldKey]?.schema,
},
};
}, {});
@@ -326,7 +335,6 @@ export const createExternalService = (
const getIssueTypes = async () => {
const capabilitiesResponse = await getCapabilities();
const supportsNewAPI = hasSupportForNewAPI(capabilitiesResponse);
-
try {
if (!supportsNewAPI) {
const res = await request({
@@ -366,7 +374,6 @@ export const createExternalService = (
const getFieldsByIssueType = async (issueTypeId: string) => {
const capabilitiesResponse = await getCapabilities();
const supportsNewAPI = hasSupportForNewAPI(capabilitiesResponse);
-
try {
if (!supportsNewAPI) {
const res = await request({
@@ -378,6 +385,7 @@ export const createExternalService = (
});
const fields = res.data.projects[0]?.issuetypes[0]?.fields || {};
+
return normalizeFields(fields);
} else {
const res = await request({
@@ -409,6 +417,30 @@ export const createExternalService = (
}
};
+ const getFields = async () => {
+ try {
+ const issueTypes = await getIssueTypes();
+ const fieldsPerIssueType = await Promise.all(
+ issueTypes.map((issueType) => getFieldsByIssueType(issueType.id))
+ );
+ return fieldsPerIssueType.reduce((acc: GetCommonFieldsResponse, fieldTypesByIssue) => {
+ const currentListOfFields = Object.keys(acc);
+ return currentListOfFields.length === 0
+ ? fieldTypesByIssue
+ : currentListOfFields.reduce(
+ (add: GetCommonFieldsResponse, field) =>
+ Object.keys(fieldTypesByIssue).includes(field)
+ ? { ...add, [field]: acc[field] }
+ : add,
+ {}
+ );
+ }, {});
+ } catch (error) {
+ // errors that happen here would be thrown in the contained async calls
+ throw error;
+ }
+ };
+
const getIssues = async (title: string) => {
const query = `${searchUrl}?jql=${encodeURIComponent(
`project="${projectKey}" and summary ~"${title}"`
@@ -461,6 +493,7 @@ export const createExternalService = (
};
return {
+ getFields,
getIncident,
createIncident,
updateIncident,
diff --git a/x-pack/plugins/actions/server/builtin_action_types/jira/types.ts b/x-pack/plugins/actions/server/builtin_action_types/jira/types.ts
index 7d650a22fba1b..e142637010a98 100644
--- a/x-pack/plugins/actions/server/builtin_action_types/jira/types.ts
+++ b/x-pack/plugins/actions/server/builtin_action_types/jira/types.ts
@@ -79,11 +79,34 @@ export interface CreateCommentParams {
comment: Comment;
}
+export interface FieldsSchema {
+ type: string;
+ [key: string]: string;
+}
+
+export interface ExternalServiceFields {
+ clauseNames: string[];
+ custom: boolean;
+ id: string;
+ key: string;
+ name: string;
+ navigatable: boolean;
+ orderable: boolean;
+ schema: FieldsSchema;
+ searchable: boolean;
+}
+
export type GetIssueTypesResponse = Array<{ id: string; name: string }>;
+
+export interface FieldSchema {
+ type: string;
+ items?: string;
+}
export type GetFieldsByIssueTypeResponse = Record<
string,
- { allowedValues: Array<{}>; defaultValue: {} }
+ { allowedValues: Array<{}>; defaultValue: {}; required: boolean; schema: FieldSchema }
>;
+export type GetCommonFieldsResponse = GetFieldsByIssueTypeResponse;
export type GetIssuesResponse = Array<{ id: string; key: string; title: string }>;
export interface GetIssueResponse {
@@ -93,15 +116,16 @@ export interface GetIssueResponse {
}
export interface ExternalService {
- getIncident: (id: string) => Promise;
- createIncident: (params: CreateIncidentParams) => Promise;
- updateIncident: (params: UpdateIncidentParams) => Promise;
createComment: (params: CreateCommentParams) => Promise;
+ createIncident: (params: CreateIncidentParams) => Promise;
+ getFields: () => Promise;
getCapabilities: () => Promise;
- getIssueTypes: () => Promise;
getFieldsByIssueType: (issueTypeId: string) => Promise;
- getIssues: (title: string) => Promise;
+ getIncident: (id: string) => Promise;
getIssue: (id: string) => Promise;
+ getIssues: (title: string) => Promise