diff --git a/x-pack/plugins/case/server/routes/api/cases/configure/patch_configure.ts b/x-pack/plugins/case/server/routes/api/cases/configure/patch_configure.ts index 47f7d503e32b8..29df97c5f8476 100644 --- a/x-pack/plugins/case/server/routes/api/cases/configure/patch_configure.ts +++ b/x-pack/plugins/case/server/routes/api/cases/configure/patch_configure.ts @@ -39,7 +39,7 @@ export function initPatchCaseConfigure({ caseConfigureService, caseService, rout if (myCaseConfigure.saved_objects.length === 0) { throw Boom.conflict( - 'You can not patch this configuration since you did not created first with a post' + 'You can not patch this configuration since you did not created first with a post.' ); } diff --git a/x-pack/test/case_api_integration/basic/config.ts b/x-pack/test/case_api_integration/basic/config.ts new file mode 100644 index 0000000000000..f9c248ec3d56f --- /dev/null +++ b/x-pack/test/case_api_integration/basic/config.ts @@ -0,0 +1,14 @@ +/* + * 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 { createTestConfig } from '../common/config'; + +// eslint-disable-next-line import/no-default-export +export default createTestConfig('basic', { + disabledPlugins: [], + license: 'basic', + ssl: true, +}); diff --git a/x-pack/test/case_api_integration/basic/tests/configure/get_configure.ts b/x-pack/test/case_api_integration/basic/tests/configure/get_configure.ts new file mode 100644 index 0000000000000..a9fc2706a6ba2 --- /dev/null +++ b/x-pack/test/case_api_integration/basic/tests/configure/get_configure.ts @@ -0,0 +1,55 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +import { CASE_CONFIGURE_URL } from '../../../../../plugins/case/common/constants'; +import { + getConfiguration, + removeServerGeneratedPropertiesFromConfigure, + getConfigurationOutput, + deleteConfiguration, +} from '../../../common/lib/utils'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext): void => { + const supertest = getService('supertest'); + const es = getService('legacyEs'); + + describe('get_configure', () => { + afterEach(async () => { + await deleteConfiguration(es); + }); + + it('should return an empty find body correctly if no configuration is loaded', async () => { + const { body } = await supertest + .get(CASE_CONFIGURE_URL) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + + expect(body).to.eql({}); + }); + + it('should return a configuration', async () => { + await supertest + .post(CASE_CONFIGURE_URL) + .set('kbn-xsrf', 'true') + .send(getConfiguration()) + .expect(200); + + const { body } = await supertest + .get(CASE_CONFIGURE_URL) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + + const data = removeServerGeneratedPropertiesFromConfigure(body); + expect(data).to.eql(getConfigurationOutput()); + }); + }); +}; diff --git a/x-pack/test/case_api_integration/basic/tests/configure/get_connectors.ts b/x-pack/test/case_api_integration/basic/tests/configure/get_connectors.ts new file mode 100644 index 0000000000000..836c76d500034 --- /dev/null +++ b/x-pack/test/case_api_integration/basic/tests/configure/get_connectors.ts @@ -0,0 +1,27 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +import { CASE_CONFIGURE_CONNECTORS_URL } from '../../../../../plugins/case/common/constants'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext): void => { + const supertest = getService('supertest'); + + describe('get_connectors', () => { + it('should return an empty find body correctly if no connectors are loaded', async () => { + const { body } = await supertest + .get(`${CASE_CONFIGURE_CONNECTORS_URL}/_find`) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + + expect(body).to.eql([]); + }); + }); +}; diff --git a/x-pack/test/case_api_integration/basic/tests/configure/patch_configure.ts b/x-pack/test/case_api_integration/basic/tests/configure/patch_configure.ts new file mode 100644 index 0000000000000..d66baa2a2eee2 --- /dev/null +++ b/x-pack/test/case_api_integration/basic/tests/configure/patch_configure.ts @@ -0,0 +1,81 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +import { CASE_CONFIGURE_URL } from '../../../../../plugins/case/common/constants'; +import { + getConfiguration, + removeServerGeneratedPropertiesFromConfigure, + getConfigurationOutput, + deleteConfiguration, +} from '../../../common/lib/utils'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext): void => { + const supertest = getService('supertest'); + const es = getService('legacyEs'); + + describe('post_configure', () => { + afterEach(async () => { + await deleteConfiguration(es); + }); + + it('should patch a configuration', async () => { + const res = await supertest + .post(CASE_CONFIGURE_URL) + .set('kbn-xsrf', 'true') + .send(getConfiguration()) + .expect(200); + + const { body } = await supertest + .patch(CASE_CONFIGURE_URL) + .set('kbn-xsrf', 'true') + .send({ closure_type: 'close-by-pushing', version: res.body.version }) + .expect(200); + + const data = removeServerGeneratedPropertiesFromConfigure(body); + expect(data).to.eql({ ...getConfigurationOutput(true), closure_type: 'close-by-pushing' }); + }); + + it('should handle patch request when there is no configuration', async () => { + const { body } = await supertest + .patch(CASE_CONFIGURE_URL) + .set('kbn-xsrf', 'true') + .send({ closure_type: 'close-by-pushing', version: 'no-version' }) + .expect(409); + + expect(body).to.eql({ + error: 'Conflict', + message: + 'You can not patch this configuration since you did not created first with a post.', + statusCode: 409, + }); + }); + + it('should handle patch request when versions are different', async () => { + await supertest + .post(CASE_CONFIGURE_URL) + .set('kbn-xsrf', 'true') + .send(getConfiguration()) + .expect(200); + + const { body } = await supertest + .patch(CASE_CONFIGURE_URL) + .set('kbn-xsrf', 'true') + .send({ closure_type: 'close-by-pushing', version: 'no-version' }) + .expect(409); + + expect(body).to.eql({ + error: 'Conflict', + message: + 'This configuration has been updated. Please refresh before saving additional updates.', + statusCode: 409, + }); + }); + }); +}; diff --git a/x-pack/test/case_api_integration/basic/tests/configure/post_configure.ts b/x-pack/test/case_api_integration/basic/tests/configure/post_configure.ts new file mode 100644 index 0000000000000..c2284492e5b77 --- /dev/null +++ b/x-pack/test/case_api_integration/basic/tests/configure/post_configure.ts @@ -0,0 +1,62 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +import { CASE_CONFIGURE_URL } from '../../../../../plugins/case/common/constants'; +import { + getConfiguration, + removeServerGeneratedPropertiesFromConfigure, + getConfigurationOutput, + deleteConfiguration, +} from '../../../common/lib/utils'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext): void => { + const supertest = getService('supertest'); + const es = getService('legacyEs'); + + describe('post_configure', () => { + afterEach(async () => { + await deleteConfiguration(es); + }); + + it('should create a configuration', async () => { + const { body } = await supertest + .post(CASE_CONFIGURE_URL) + .set('kbn-xsrf', 'true') + .send(getConfiguration()) + .expect(200); + + const data = removeServerGeneratedPropertiesFromConfigure(body); + expect(data).to.eql(getConfigurationOutput()); + }); + + it('should keep only the latest configuration', async () => { + await supertest + .post(CASE_CONFIGURE_URL) + .set('kbn-xsrf', 'true') + .send(getConfiguration('connector-2')) + .expect(200); + + await supertest + .post(CASE_CONFIGURE_URL) + .set('kbn-xsrf', 'true') + .send(getConfiguration()) + .expect(200); + + const { body } = await supertest + .get(CASE_CONFIGURE_URL) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + + const data = removeServerGeneratedPropertiesFromConfigure(body); + expect(data).to.eql(getConfigurationOutput()); + }); + }); +}; diff --git a/x-pack/test/case_api_integration/basic/tests/index.ts b/x-pack/test/case_api_integration/basic/tests/index.ts new file mode 100644 index 0000000000000..efd5369c019d8 --- /dev/null +++ b/x-pack/test/case_api_integration/basic/tests/index.ts @@ -0,0 +1,20 @@ +/* + * 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 { FtrProviderContext } from '../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default ({ loadTestFile }: FtrProviderContext): void => { + describe('case api basic', function() { + // Fastest ciGroup for the moment. + this.tags('ciGroup2'); + + loadTestFile(require.resolve('./configure/get_configure')); + loadTestFile(require.resolve('./configure/post_configure')); + loadTestFile(require.resolve('./configure/patch_configure')); + loadTestFile(require.resolve('./configure/get_connectors')); + }); +}; diff --git a/x-pack/test/case_api_integration/common/config.ts b/x-pack/test/case_api_integration/common/config.ts new file mode 100644 index 0000000000000..862705ab9610b --- /dev/null +++ b/x-pack/test/case_api_integration/common/config.ts @@ -0,0 +1,94 @@ +/* + * 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 path from 'path'; + +import { CA_CERT_PATH } from '@kbn/dev-utils'; +import { FtrConfigProviderContext } from '@kbn/test/types/ftr'; + +import { services } from './services'; + +interface CreateTestConfigOptions { + license: string; + disabledPlugins?: string[]; + ssl?: boolean; +} + +// test.not-enabled is specifically not enabled +const enabledActionTypes = [ + '.email', + '.index', + '.pagerduty', + '.server-log', + '.servicenow', + '.slack', + '.webhook', + 'test.authorization', + 'test.failing', + 'test.index-record', + 'test.noop', + 'test.rate-limit', +]; + +export function createTestConfig(name: string, options: CreateTestConfigOptions) { + const { license = 'trial', disabledPlugins = [], ssl = false } = options; + + return async ({ readConfigFile }: FtrConfigProviderContext) => { + const xPackApiIntegrationTestsConfig = await readConfigFile( + require.resolve('../../api_integration/config.js') + ); + + const servers = { + ...xPackApiIntegrationTestsConfig.get('servers'), + elasticsearch: { + ...xPackApiIntegrationTestsConfig.get('servers.elasticsearch'), + protocol: ssl ? 'https' : 'http', + }, + }; + + return { + testFiles: [require.resolve(`../${name}/tests/`)], + servers, + services, + junit: { + reportName: 'X-Pack Case API Integration Tests', + }, + esArchiver: xPackApiIntegrationTestsConfig.get('esArchiver'), + esTestCluster: { + ...xPackApiIntegrationTestsConfig.get('esTestCluster'), + license, + ssl, + serverArgs: [ + `xpack.license.self_generated.type=${license}`, + `xpack.security.enabled=${!disabledPlugins.includes('security') && + ['trial', 'basic'].includes(license)}`, + ], + }, + kbnTestServer: { + ...xPackApiIntegrationTestsConfig.get('kbnTestServer'), + serverArgs: [ + ...xPackApiIntegrationTestsConfig.get('kbnTestServer.serverArgs'), + `--xpack.actions.whitelistedHosts=${JSON.stringify([ + 'localhost', + 'some.non.existent.com', + ])}`, + `--xpack.actions.enabledActionTypes=${JSON.stringify(enabledActionTypes)}`, + '--xpack.alerting.enabled=true', + '--xpack.eventLog.logEntries=true', + ...disabledPlugins.map(key => `--xpack.${key}.enabled=false`), + `--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'alerts')}`, + `--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'actions')}`, + ...(ssl + ? [ + `--elasticsearch.hosts=${servers.elasticsearch.protocol}://${servers.elasticsearch.hostname}:${servers.elasticsearch.port}`, + `--elasticsearch.ssl.certificateAuthorities=${CA_CERT_PATH}`, + ] + : []), + ], + }, + }; + }; +} diff --git a/x-pack/test/case_api_integration/common/ftr_provider_context.d.ts b/x-pack/test/case_api_integration/common/ftr_provider_context.d.ts new file mode 100644 index 0000000000000..e3add3748f56d --- /dev/null +++ b/x-pack/test/case_api_integration/common/ftr_provider_context.d.ts @@ -0,0 +1,11 @@ +/* + * 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 { GenericFtrProviderContext } from '@kbn/test/types/ftr'; + +import { services } from './services'; + +export type FtrProviderContext = GenericFtrProviderContext; diff --git a/x-pack/test/case_api_integration/common/lib/utils.ts b/x-pack/test/case_api_integration/common/lib/utils.ts new file mode 100644 index 0000000000000..6d0db69309b90 --- /dev/null +++ b/x-pack/test/case_api_integration/common/lib/utils.ts @@ -0,0 +1,71 @@ +/* + * 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 { CasesConfigureRequest, CasesConfigureResponse } from '../../../../plugins/case/common/api'; + +export const getConfiguration = (connector_id: string = 'connector-1'): CasesConfigureRequest => { + return { + connector_id, + connector_name: 'Connector 1', + closure_type: 'close-by-user', + }; +}; + +export const getConfigurationOutput = (update = false): Partial => { + return { + ...getConfiguration(), + created_by: { email: null, full_name: null, username: 'elastic' }, + updated_by: update ? { email: null, full_name: null, username: 'elastic' } : null, + }; +}; + +export const removeServerGeneratedPropertiesFromConfigure = ( + config: Partial +): Partial => { + const { created_at, updated_at, version, ...rest } = config; + return rest; +}; + +export const deleteConfiguration = async (es: any): Promise => { + await es.deleteByQuery({ + index: '.kibana', + q: 'type:cases-configure', + waitForCompletion: true, + refresh: 'wait_for', + body: {}, + }); +}; + +export const getConnector = () => ({ + name: 'ServiceNow Connector', + actionTypeId: '.servicenow', + secrets: { + username: 'admin', + password: 'admin', + }, + config: { + apiUrl: 'localhost', + casesConfiguration: { + mapping: [ + { + source: 'title', + target: 'short_description', + actionType: 'overwrite', + }, + { + source: 'description', + target: 'description', + actionType: 'overwrite', + }, + { + source: 'comments', + target: 'comments', + actionType: 'append', + }, + ], + }, + }, +}); diff --git a/x-pack/test/case_api_integration/common/services.ts b/x-pack/test/case_api_integration/common/services.ts new file mode 100644 index 0000000000000..a927a31469bab --- /dev/null +++ b/x-pack/test/case_api_integration/common/services.ts @@ -0,0 +1,7 @@ +/* + * 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. + */ + +export { services } from '../../api_integration/services';