From 20826486784fc2cd154218a773aeef7fafe80fb8 Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Mon, 11 May 2020 14:27:02 -0600 Subject: [PATCH] [SIEM] [Cases] Case API tests (#65777) --- .../tests/cases/comments/delete_comment.ts | 76 +++++ .../tests/cases/comments/find_comments.ts | 93 ++++++ .../basic/tests/cases/comments/get_comment.ts | 53 +++ .../tests/cases/comments/patch_comment.ts | 123 +++++++ .../tests/cases/comments/post_comment.ts | 57 ++++ .../basic/tests/cases/delete_cases.ts | 76 +++++ .../basic/tests/cases/find_cases.ts | 158 +++++++++ .../basic/tests/cases/get_case.ts | 52 +++ .../basic/tests/cases/patch_cases.ts | 139 ++++++++ .../basic/tests/cases/post_case.ts | 46 +++ .../basic/tests/cases/push_case.ts | 161 +++++++++ .../tests/cases/reporters/get_reporters.ts | 40 +++ .../basic/tests/cases/status/get_status.ts | 59 ++++ .../basic/tests/cases/tags/get_tags.ts | 43 +++ .../user_actions/get_all_user_actions.ts | 307 ++++++++++++++++++ .../case_api_integration/basic/tests/index.ts | 19 +- .../case_api_integration/common/lib/mock.ts | 50 +++ .../case_api_integration/common/lib/utils.ts | 61 ++-- 18 files changed, 1580 insertions(+), 33 deletions(-) create mode 100644 x-pack/test/case_api_integration/basic/tests/cases/comments/delete_comment.ts create mode 100644 x-pack/test/case_api_integration/basic/tests/cases/comments/find_comments.ts create mode 100644 x-pack/test/case_api_integration/basic/tests/cases/comments/get_comment.ts create mode 100644 x-pack/test/case_api_integration/basic/tests/cases/comments/patch_comment.ts create mode 100644 x-pack/test/case_api_integration/basic/tests/cases/comments/post_comment.ts create mode 100644 x-pack/test/case_api_integration/basic/tests/cases/delete_cases.ts create mode 100644 x-pack/test/case_api_integration/basic/tests/cases/find_cases.ts create mode 100644 x-pack/test/case_api_integration/basic/tests/cases/get_case.ts create mode 100644 x-pack/test/case_api_integration/basic/tests/cases/patch_cases.ts create mode 100644 x-pack/test/case_api_integration/basic/tests/cases/post_case.ts create mode 100644 x-pack/test/case_api_integration/basic/tests/cases/push_case.ts create mode 100644 x-pack/test/case_api_integration/basic/tests/cases/reporters/get_reporters.ts create mode 100644 x-pack/test/case_api_integration/basic/tests/cases/status/get_status.ts create mode 100644 x-pack/test/case_api_integration/basic/tests/cases/tags/get_tags.ts create mode 100644 x-pack/test/case_api_integration/basic/tests/cases/user_actions/get_all_user_actions.ts create mode 100644 x-pack/test/case_api_integration/common/lib/mock.ts diff --git a/x-pack/test/case_api_integration/basic/tests/cases/comments/delete_comment.ts b/x-pack/test/case_api_integration/basic/tests/cases/comments/delete_comment.ts new file mode 100644 index 0000000000000..afae04ae9cf5b --- /dev/null +++ b/x-pack/test/case_api_integration/basic/tests/cases/comments/delete_comment.ts @@ -0,0 +1,76 @@ +/* + * 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 { CASES_URL } from '../../../../../../plugins/case/common/constants'; +import { postCaseReq, postCommentReq } from '../../../../common/lib/mock'; +import { deleteCases, deleteCasesUserActions, deleteComments } from '../../../../common/lib/utils'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext): void => { + const supertest = getService('supertest'); + const es = getService('es'); + + describe('delete_comment', () => { + afterEach(async () => { + await deleteCases(es); + await deleteComments(es); + await deleteCasesUserActions(es); + }); + + it('should delete a comment', async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq) + .expect(200); + + const { body: patchedCase } = await supertest + .post(`${CASES_URL}/${postedCase.id}/comments`) + .set('kbn-xsrf', 'true') + .send(postCommentReq); + + const { body: comment } = await supertest + .delete(`${CASES_URL}/${postedCase.id}/comments/${patchedCase.comments[0].id}`) + .set('kbn-xsrf', 'true') + .send(); + + expect(comment).to.eql({}); + }); + + it('unhappy path - 404s when comment belongs to different case', async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq) + .expect(200); + + const { body: patchedCase } = await supertest + .post(`${CASES_URL}/${postedCase.id}/comments`) + .set('kbn-xsrf', 'true') + .send(postCommentReq); + + const { body } = await supertest + .delete(`${CASES_URL}/fake-id/comments/${patchedCase.comments[0].id}`) + .set('kbn-xsrf', 'true') + .send() + .expect(404); + expect(body.message).to.eql( + `This comment ${patchedCase.comments[0].id} does not exist in fake-id).` + ); + }); + + it('unhappy path - 404s when comment is not there', async () => { + await supertest + .delete(`${CASES_URL}/fake-id/comments/fake-id`) + .set('kbn-xsrf', 'true') + .send() + .expect(404); + }); + }); +}; diff --git a/x-pack/test/case_api_integration/basic/tests/cases/comments/find_comments.ts b/x-pack/test/case_api_integration/basic/tests/cases/comments/find_comments.ts new file mode 100644 index 0000000000000..e5c44de90b5a1 --- /dev/null +++ b/x-pack/test/case_api_integration/basic/tests/cases/comments/find_comments.ts @@ -0,0 +1,93 @@ +/* + * 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 { CASES_URL } from '../../../../../../plugins/case/common/constants'; +import { postCaseReq, postCommentReq } from '../../../../common/lib/mock'; +import { deleteCases, deleteCasesUserActions, deleteComments } from '../../../../common/lib/utils'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext): void => { + const supertest = getService('supertest'); + const es = getService('es'); + + describe('find_comments', () => { + afterEach(async () => { + await deleteCases(es); + await deleteComments(es); + await deleteCasesUserActions(es); + }); + + it('should find all case comment', async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq) + .expect(200); + // post 2 comments + await supertest + .post(`${CASES_URL}/${postedCase.id}/comments`) + .set('kbn-xsrf', 'true') + .send(postCommentReq); + + const { body: patchedCase } = await supertest + .post(`${CASES_URL}/${postedCase.id}/comments`) + .set('kbn-xsrf', 'true') + .send(postCommentReq); + + const { body: caseComments } = await supertest + .get(`${CASES_URL}/${postedCase.id}/comments/_find`) + .set('kbn-xsrf', 'true') + .send(); + + expect(caseComments.comments).to.eql(patchedCase.comments); + }); + + it('should filter case comments', async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq) + .expect(200); + // post 2 comments + await supertest + .post(`${CASES_URL}/${postedCase.id}/comments`) + .set('kbn-xsrf', 'true') + .send(postCommentReq); + + const { body: patchedCase } = await supertest + .post(`${CASES_URL}/${postedCase.id}/comments`) + .set('kbn-xsrf', 'true') + .send({ comment: 'unique' }); + + const { body: caseComments } = await supertest + .get(`${CASES_URL}/${postedCase.id}/comments/_find?search=unique`) + .set('kbn-xsrf', 'true') + .send(); + + expect(caseComments.comments).to.eql([patchedCase.comments[1]]); + }); + + it('unhappy path - 400s when query is bad', async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq) + .expect(200); + await supertest + .post(`${CASES_URL}/${postedCase.id}/comments`) + .set('kbn-xsrf', 'true') + .send(postCommentReq); + await supertest + .get(`${CASES_URL}/${postedCase.id}/comments/_find?perPage=true`) + .set('kbn-xsrf', 'true') + .send() + .expect(400); + }); + }); +}; diff --git a/x-pack/test/case_api_integration/basic/tests/cases/comments/get_comment.ts b/x-pack/test/case_api_integration/basic/tests/cases/comments/get_comment.ts new file mode 100644 index 0000000000000..53da0ef1d2b16 --- /dev/null +++ b/x-pack/test/case_api_integration/basic/tests/cases/comments/get_comment.ts @@ -0,0 +1,53 @@ +/* + * 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 { CASES_URL } from '../../../../../../plugins/case/common/constants'; +import { postCaseReq, postCommentReq } from '../../../../common/lib/mock'; +import { deleteCases, deleteCasesUserActions, deleteComments } from '../../../../common/lib/utils'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext): void => { + const supertest = getService('supertest'); + const es = getService('es'); + + describe('get_comment', () => { + afterEach(async () => { + await deleteCases(es); + await deleteComments(es); + await deleteCasesUserActions(es); + }); + + it('should get a comment', async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq); + + const { body: patchedCase } = await supertest + .post(`${CASES_URL}/${postedCase.id}/comments`) + .set('kbn-xsrf', 'true') + .send(postCommentReq); + + const { body: comment } = await supertest + .get(`${CASES_URL}/${postedCase.id}/comments/${patchedCase.comments[0].id}`) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + + expect(comment).to.eql(patchedCase.comments[0]); + }); + it('unhappy path - 404s when comment is not there', async () => { + await supertest + .get(`${CASES_URL}/fake-id/comments/fake-comment`) + .set('kbn-xsrf', 'true') + .send() + .expect(404); + }); + }); +}; diff --git a/x-pack/test/case_api_integration/basic/tests/cases/comments/patch_comment.ts b/x-pack/test/case_api_integration/basic/tests/cases/comments/patch_comment.ts new file mode 100644 index 0000000000000..73aeeb0fb989a --- /dev/null +++ b/x-pack/test/case_api_integration/basic/tests/cases/comments/patch_comment.ts @@ -0,0 +1,123 @@ +/* + * 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 { CASES_URL } from '../../../../../../plugins/case/common/constants'; +import { defaultUser, postCaseReq, postCommentReq } from '../../../../common/lib/mock'; +import { deleteCases, deleteCasesUserActions, deleteComments } from '../../../../common/lib/utils'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext): void => { + const supertest = getService('supertest'); + const es = getService('es'); + + describe('patch_comment', () => { + afterEach(async () => { + await deleteCases(es); + await deleteComments(es); + await deleteCasesUserActions(es); + }); + + it('should patch a comment', async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq) + .expect(200); + + const { body: patchedCase } = await supertest + .post(`${CASES_URL}/${postedCase.id}/comments`) + .set('kbn-xsrf', 'true') + .send(postCommentReq); + const newComment = 'Well I decided to update my comment. So what? Deal with it.'; + const { body } = await supertest + .patch(`${CASES_URL}/${postedCase.id}/comments`) + .set('kbn-xsrf', 'true') + .send({ + id: patchedCase.comments[0].id, + version: patchedCase.comments[0].version, + comment: newComment, + }); + expect(body.comments[0].comment).to.eql(newComment); + expect(body.updated_by).to.eql(defaultUser); + }); + + it('unhappy path - 404s when comment is not there', async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq); + await supertest + .patch(`${CASES_URL}/${postedCase.id}/comments`) + .set('kbn-xsrf', 'true') + .send({ + id: 'id', + version: 'version', + comment: 'comment', + }) + .expect(404); + }); + + it('unhappy path - 404s when case is not there', async () => { + await supertest + .patch(`${CASES_URL}/fake-id/comments`) + .set('kbn-xsrf', 'true') + .send({ + id: 'id', + version: 'version', + comment: 'comment', + }) + .expect(404); + }); + + it('unhappy path - 400s when patch body is bad', async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq) + .expect(200); + + const { body: patchedCase } = await supertest + .post(`${CASES_URL}/${postedCase.id}/comments`) + .set('kbn-xsrf', 'true') + .send(postCommentReq); + await supertest + .patch(`${CASES_URL}/${postedCase.id}/comments`) + .set('kbn-xsrf', 'true') + .send({ + id: patchedCase.comments[0].id, + version: patchedCase.comments[0].version, + comment: true, + }) + .expect(400); + }); + + it('unhappy path - 409s when conflict', async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq) + .expect(200); + + const { body: patchedCase } = await supertest + .post(`${CASES_URL}/${postedCase.id}/comments`) + .set('kbn-xsrf', 'true') + .send(postCommentReq); + const newComment = 'Well I decided to update my comment. So what? Deal with it.'; + await supertest + .patch(`${CASES_URL}/${postedCase.id}/comments`) + .set('kbn-xsrf', 'true') + .send({ + id: patchedCase.comments[0].id, + version: 'version-mismatch', + comment: newComment, + }) + .expect(409); + }); + }); +}; diff --git a/x-pack/test/case_api_integration/basic/tests/cases/comments/post_comment.ts b/x-pack/test/case_api_integration/basic/tests/cases/comments/post_comment.ts new file mode 100644 index 0000000000000..6e8353f8ea86a --- /dev/null +++ b/x-pack/test/case_api_integration/basic/tests/cases/comments/post_comment.ts @@ -0,0 +1,57 @@ +/* + * 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 { CASES_URL } from '../../../../../../plugins/case/common/constants'; +import { defaultUser, postCaseReq, postCommentReq } from '../../../../common/lib/mock'; +import { deleteCases, deleteCasesUserActions, deleteComments } from '../../../../common/lib/utils'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext): void => { + const supertest = getService('supertest'); + const es = getService('es'); + + describe('post_comment', () => { + afterEach(async () => { + await deleteCases(es); + await deleteComments(es); + await deleteCasesUserActions(es); + }); + + it('should post a comment', async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq) + .expect(200); + + const { body: patchedCase } = await supertest + .post(`${CASES_URL}/${postedCase.id}/comments`) + .set('kbn-xsrf', 'true') + .send(postCommentReq); + expect(patchedCase.comments[0].comment).to.eql(postCommentReq.comment); + expect(patchedCase.updated_by).to.eql(defaultUser); + }); + + it('unhappy path - 400s when post body is bad', async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq) + .expect(200); + + await supertest + .post(`${CASES_URL}/${postedCase.id}/comments`) + .set('kbn-xsrf', 'true') + .send({ + bad: 'comment', + }) + .expect(400); + }); + }); +}; diff --git a/x-pack/test/case_api_integration/basic/tests/cases/delete_cases.ts b/x-pack/test/case_api_integration/basic/tests/cases/delete_cases.ts new file mode 100644 index 0000000000000..aa2465e44c5c1 --- /dev/null +++ b/x-pack/test/case_api_integration/basic/tests/cases/delete_cases.ts @@ -0,0 +1,76 @@ +/* + * 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 { CASES_URL } from '../../../../../plugins/case/common/constants'; +import { postCaseReq, postCommentReq } from '../../../common/lib/mock'; +import { deleteCases, deleteCasesUserActions, deleteComments } from '../../../common/lib/utils'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext): void => { + const supertest = getService('supertest'); + const es = getService('es'); + + describe('delete_cases', () => { + afterEach(async () => { + await deleteCases(es); + await deleteComments(es); + await deleteCasesUserActions(es); + }); + + it('should delete a case', async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq); + + const { body } = await supertest + .delete(`${CASES_URL}?ids=["${postedCase.id}"]`) + .set('kbn-xsrf', 'true') + .send() + .expect(204); + + expect(body).to.eql({}); + }); + + it(`should delete a case's comments when that case gets deleted`, async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq); + + const { body: patchedCase } = await supertest + .post(`${CASES_URL}/${postedCase.id}/comments`) + .set('kbn-xsrf', 'true') + .send(postCommentReq); + + await supertest + .get(`${CASES_URL}/${postedCase.id}/comments/${patchedCase.comments[0].id}`) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + await supertest + .delete(`${CASES_URL}?ids=["${postedCase.id}"]`) + .set('kbn-xsrf', 'true') + .send() + .expect(204); + await supertest + .get(`${CASES_URL}/${postedCase.id}/comments/${patchedCase.comments[0].id}`) + .set('kbn-xsrf', 'true') + .send() + .expect(404); + }); + it('unhappy path - 404s when case is not there', async () => { + await supertest + .delete(`${CASES_URL}?ids=["fake-id"]`) + .set('kbn-xsrf', 'true') + .send() + .expect(404); + }); + }); +}; diff --git a/x-pack/test/case_api_integration/basic/tests/cases/find_cases.ts b/x-pack/test/case_api_integration/basic/tests/cases/find_cases.ts new file mode 100644 index 0000000000000..04d195ea73509 --- /dev/null +++ b/x-pack/test/case_api_integration/basic/tests/cases/find_cases.ts @@ -0,0 +1,158 @@ +/* + * 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 { CASES_URL } from '../../../../../plugins/case/common/constants'; +import { postCaseReq, postCommentReq, findCasesResp } from '../../../common/lib/mock'; +import { deleteCases, deleteComments, deleteCasesUserActions } from '../../../common/lib/utils'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext): void => { + const supertest = getService('supertest'); + const es = getService('es'); + describe('find_cases', () => { + afterEach(async () => { + await deleteCases(es); + await deleteComments(es); + await deleteCasesUserActions(es); + }); + it('should return empty response', async () => { + const { body } = await supertest + .get(`${CASES_URL}/_find`) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + + expect(body).to.eql(findCasesResp); + }); + + it('should return cases', async () => { + const { body: a } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq); + const { body: b } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq); + const { body: c } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq); + const { body } = await supertest + .get(`${CASES_URL}/_find?sortOrder=asc`) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + + expect(body).to.eql({ + ...findCasesResp, + total: 3, + cases: [a, b, c], + count_open_cases: 3, + }); + }); + + it('filters by tags', async () => { + await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq); + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send({ ...postCaseReq, tags: ['unique'] }); + const { body } = await supertest + .get(`${CASES_URL}/_find?sortOrder=asc&tags=unique`) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + + expect(body).to.eql({ + ...findCasesResp, + total: 1, + cases: [postedCase], + count_open_cases: 1, + }); + }); + + it('correctly counts comments', async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq); + + // post 2 comments + await supertest + .post(`${CASES_URL}/${postedCase.id}/comments`) + .set('kbn-xsrf', 'true') + .send(postCommentReq); + const { body: patchedCase } = await supertest + .post(`${CASES_URL}/${postedCase.id}/comments`) + .set('kbn-xsrf', 'true') + .send(postCommentReq); + const { body } = await supertest + .get(`${CASES_URL}/_find?sortOrder=asc`) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + + expect(body).to.eql({ + ...findCasesResp, + total: 1, + cases: [ + { + ...patchedCase, + comments: [], + totalComment: 2, + }, + ], + count_open_cases: 1, + }); + }); + + it('correctly counts open/closed', async () => { + await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq); + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq); + await supertest + .patch(CASES_URL) + .set('kbn-xsrf', 'true') + .send({ + cases: [ + { + id: postedCase.id, + version: postedCase.version, + status: 'closed', + }, + ], + }) + .expect(200); + const { body } = await supertest + .get(`${CASES_URL}/_find?sortOrder=asc`) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + + expect(body.count_open_cases).to.eql(1); + expect(body.count_closed_cases).to.eql(1); + }); + it('unhappy path - 400s when bad query supplied', async () => { + await supertest + .get(`${CASES_URL}/_find?perPage=true`) + .set('kbn-xsrf', 'true') + .send() + .expect(400); + }); + }); +}; diff --git a/x-pack/test/case_api_integration/basic/tests/cases/get_case.ts b/x-pack/test/case_api_integration/basic/tests/cases/get_case.ts new file mode 100644 index 0000000000000..9aad86126ceaf --- /dev/null +++ b/x-pack/test/case_api_integration/basic/tests/cases/get_case.ts @@ -0,0 +1,52 @@ +/* + * 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 { CASES_URL } from '../../../../../plugins/case/common/constants'; +import { + postCaseReq, + postCaseResp, + removeServerGeneratedPropertiesFromCase, +} from '../../../common/lib/mock'; +import { deleteCases } from '../../../common/lib/utils'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext): void => { + const supertest = getService('supertest'); + const es = getService('es'); + + describe('get_case', () => { + afterEach(async () => { + await deleteCases(es); + }); + + it('should return a case', async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq) + .expect(200); + + const { body } = await supertest + .get(`${CASES_URL}/${postedCase.id}`) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + + const data = removeServerGeneratedPropertiesFromCase(body); + expect(data).to.eql(postCaseResp(postedCase.id)); + }); + it('unhappy path - 404s when case is not there', async () => { + await supertest + .get(`${CASES_URL}/fake-id`) + .set('kbn-xsrf', 'true') + .send() + .expect(404); + }); + }); +}; diff --git a/x-pack/test/case_api_integration/basic/tests/cases/patch_cases.ts b/x-pack/test/case_api_integration/basic/tests/cases/patch_cases.ts new file mode 100644 index 0000000000000..caeaf46cbc953 --- /dev/null +++ b/x-pack/test/case_api_integration/basic/tests/cases/patch_cases.ts @@ -0,0 +1,139 @@ +/* + * 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 { CASES_URL } from '../../../../../plugins/case/common/constants'; +import { + defaultUser, + postCaseReq, + postCaseResp, + removeServerGeneratedPropertiesFromCase, +} from '../../../common/lib/mock'; +import { deleteCases, deleteCasesUserActions } from '../../../common/lib/utils'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext): void => { + const supertest = getService('supertest'); + const es = getService('es'); + + describe('patch_cases', () => { + afterEach(async () => { + await deleteCases(es); + await deleteCasesUserActions(es); + }); + + it('should patch a case', async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq) + .expect(200); + const { body: patchedCases } = await supertest + .patch(CASES_URL) + .set('kbn-xsrf', 'true') + .send({ + cases: [ + { + id: postedCase.id, + version: postedCase.version, + status: 'closed', + }, + ], + }) + .expect(200); + + const data = removeServerGeneratedPropertiesFromCase(patchedCases[0]); + expect(data).to.eql({ + ...postCaseResp(postedCase.id), + closed_by: defaultUser, + status: 'closed', + updated_by: defaultUser, + }); + }); + + it('unhappy path - 404s when case is not there', async () => { + await supertest + .patch(CASES_URL) + .set('kbn-xsrf', 'true') + .send({ + cases: [ + { + id: 'not-real', + version: 'version', + status: 'closed', + }, + ], + }) + .expect(404); + }); + + it('unhappy path - 406s when excess data sent', async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq) + .expect(200); + await supertest + .patch(CASES_URL) + .set('kbn-xsrf', 'true') + .send({ + cases: [ + { + id: postedCase.id, + version: postedCase.version, + badKey: 'closed', + }, + ], + }) + .expect(406); + }); + + it('unhappy path - 400s when bad data sent', async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq) + .expect(200); + await supertest + .patch(CASES_URL) + .set('kbn-xsrf', 'true') + .send({ + cases: [ + { + id: postedCase.id, + version: postedCase.version, + status: true, + }, + ], + }) + .expect(400); + }); + + it('unhappy path - 409s when conflict', async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq) + .expect(200); + + await supertest + .patch(`${CASES_URL}`) + .set('kbn-xsrf', 'true') + .send({ + cases: [ + { + id: postedCase.id, + version: 'version', + status: 'closed', + }, + ], + }) + .expect(409); + }); + }); +}; diff --git a/x-pack/test/case_api_integration/basic/tests/cases/post_case.ts b/x-pack/test/case_api_integration/basic/tests/cases/post_case.ts new file mode 100644 index 0000000000000..ab668c2c32725 --- /dev/null +++ b/x-pack/test/case_api_integration/basic/tests/cases/post_case.ts @@ -0,0 +1,46 @@ +/* + * 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 { CASES_URL } from '../../../../../plugins/case/common/constants'; +import { + postCaseReq, + postCaseResp, + removeServerGeneratedPropertiesFromCase, +} from '../../../common/lib/mock'; +import { deleteCases } from '../../../common/lib/utils'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext): void => { + const supertest = getService('supertest'); + const es = getService('es'); + + describe('post_case', () => { + afterEach(async () => { + await deleteCases(es); + }); + + it('should post a case', async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq) + .expect(200); + + const data = removeServerGeneratedPropertiesFromCase(postedCase); + expect(data).to.eql(postCaseResp(postedCase.id)); + }); + it('unhappy path - 400s when bad query supplied', async () => { + await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send({ ...postCaseReq, badKey: true }) + .expect(400); + }); + }); +}; diff --git a/x-pack/test/case_api_integration/basic/tests/cases/push_case.ts b/x-pack/test/case_api_integration/basic/tests/cases/push_case.ts new file mode 100644 index 0000000000000..848b980dee769 --- /dev/null +++ b/x-pack/test/case_api_integration/basic/tests/cases/push_case.ts @@ -0,0 +1,161 @@ +/* + * 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, CASES_URL } from '../../../../../plugins/case/common/constants'; +import { postCaseReq, defaultUser, postCommentReq } from '../../../common/lib/mock'; +import { + deleteCases, + deleteCasesUserActions, + deleteComments, + deleteConfiguration, + getConfiguration, +} from '../../../common/lib/utils'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext): void => { + const supertest = getService('supertest'); + const es = getService('es'); + + describe('push_case', () => { + afterEach(async () => { + await deleteCases(es); + await deleteComments(es); + await deleteConfiguration(es); + await deleteCasesUserActions(es); + }); + + it('should push a case', async () => { + const { body: configure } = await supertest + .post(CASE_CONFIGURE_URL) + .set('kbn-xsrf', 'true') + .send(getConfiguration()) + .expect(200); + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq) + .expect(200); + + const { body } = await supertest + .post(`${CASES_URL}/${postedCase.id}/_push`) + .set('kbn-xsrf', 'true') + .send({ + connector_id: configure.connector_id, + connector_name: configure.connector_name, + external_id: 'external_id', + external_title: 'external_title', + external_url: 'external_url', + }) + .expect(200); + expect(body.connector_id).to.eql(configure.connector_id); + expect(body.external_service.pushed_by).to.eql(defaultUser); + }); + + it('pushes a comment appropriately', async () => { + const { body: configure } = await supertest + .post(CASE_CONFIGURE_URL) + .set('kbn-xsrf', 'true') + .send(getConfiguration()) + .expect(200); + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq) + .expect(200); + + await supertest + .post(`${CASES_URL}/${postedCase.id}/_push`) + .set('kbn-xsrf', 'true') + .send({ + connector_id: configure.connector_id, + connector_name: configure.connector_name, + external_id: 'external_id', + external_title: 'external_title', + external_url: 'external_url', + }) + .expect(200); + + await supertest + .post(`${CASES_URL}/${postedCase.id}/comments`) + .set('kbn-xsrf', 'true') + .send(postCommentReq); + + const { body } = await supertest + .post(`${CASES_URL}/${postedCase.id}/_push`) + .set('kbn-xsrf', 'true') + .send({ + connector_id: configure.connector_id, + connector_name: configure.connector_name, + external_id: 'external_id', + external_title: 'external_title', + external_url: 'external_url', + }) + .expect(200); + expect(body.comments[0].pushed_by).to.eql(defaultUser); + }); + it('unhappy path - 404s when case does not exist', async () => { + await supertest + .post(`${CASES_URL}/fake-id/_push`) + .set('kbn-xsrf', 'true') + .send({ + connector_id: 'connector_id', + connector_name: 'connector_name', + external_id: 'external_id', + external_title: 'external_title', + external_url: 'external_url', + }) + .expect(404); + }); + it('unhappy path - 400s when bad data supplied', async () => { + await supertest + .post(`${CASES_URL}/fake-id/_push`) + .set('kbn-xsrf', 'true') + .send({ + badKey: 'connector_id', + }) + .expect(400); + }); + it('unhappy path = 409s when case is closed', async () => { + const { body: configure } = await supertest + .post(CASE_CONFIGURE_URL) + .set('kbn-xsrf', 'true') + .send(getConfiguration()) + .expect(200); + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq) + .expect(200); + await supertest + .patch(CASES_URL) + .set('kbn-xsrf', 'true') + .send({ + cases: [ + { + id: postedCase.id, + version: postedCase.version, + status: 'closed', + }, + ], + }) + .expect(200); + await supertest + .post(`${CASES_URL}/${postedCase.id}/_push`) + .set('kbn-xsrf', 'true') + .send({ + connector_id: configure.connector_id, + connector_name: configure.connector_name, + external_id: 'external_id', + external_title: 'external_title', + external_url: 'external_url', + }) + .expect(409); + }); + }); +}; diff --git a/x-pack/test/case_api_integration/basic/tests/cases/reporters/get_reporters.ts b/x-pack/test/case_api_integration/basic/tests/cases/reporters/get_reporters.ts new file mode 100644 index 0000000000000..a781b928b2b68 --- /dev/null +++ b/x-pack/test/case_api_integration/basic/tests/cases/reporters/get_reporters.ts @@ -0,0 +1,40 @@ +/* + * 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 { CASES_URL, CASE_REPORTERS_URL } from '../../../../../../plugins/case/common/constants'; +import { defaultUser, postCaseReq } from '../../../../common/lib/mock'; +import { deleteCases } from '../../../../common/lib/utils'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext): void => { + const supertest = getService('supertest'); + const es = getService('es'); + + describe('get_reporters', () => { + afterEach(async () => { + await deleteCases(es); + }); + + it('should return reporters', async () => { + await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq) + .expect(200); + + const { body } = await supertest + .get(CASE_REPORTERS_URL) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + + expect(body).to.eql([defaultUser]); + }); + }); +}; diff --git a/x-pack/test/case_api_integration/basic/tests/cases/status/get_status.ts b/x-pack/test/case_api_integration/basic/tests/cases/status/get_status.ts new file mode 100644 index 0000000000000..6552f588bdc19 --- /dev/null +++ b/x-pack/test/case_api_integration/basic/tests/cases/status/get_status.ts @@ -0,0 +1,59 @@ +/* + * 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 { CASES_URL, CASE_STATUS_URL } from '../../../../../../plugins/case/common/constants'; +import { postCaseReq } from '../../../../common/lib/mock'; +import { deleteCases } from '../../../../common/lib/utils'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext): void => { + const supertest = getService('supertest'); + const es = getService('es'); + + describe('get_status', () => { + afterEach(async () => { + await deleteCases(es); + }); + + it('should return case statuses', async () => { + await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq); + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq); + await supertest + .patch(CASES_URL) + .set('kbn-xsrf', 'true') + .send({ + cases: [ + { + id: postedCase.id, + version: postedCase.version, + status: 'closed', + }, + ], + }) + .expect(200); + + const { body } = await supertest + .get(CASE_STATUS_URL) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + + expect(body).to.eql({ + count_open_cases: 1, + count_closed_cases: 1, + }); + }); + }); +}; diff --git a/x-pack/test/case_api_integration/basic/tests/cases/tags/get_tags.ts b/x-pack/test/case_api_integration/basic/tests/cases/tags/get_tags.ts new file mode 100644 index 0000000000000..9b769e3c5eef4 --- /dev/null +++ b/x-pack/test/case_api_integration/basic/tests/cases/tags/get_tags.ts @@ -0,0 +1,43 @@ +/* + * 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 { CASES_URL, CASE_TAGS_URL } from '../../../../../../plugins/case/common/constants'; +import { postCaseReq } from '../../../../common/lib/mock'; +import { deleteCases } from '../../../../common/lib/utils'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext): void => { + const supertest = getService('supertest'); + const es = getService('es'); + + describe('get_tags', () => { + afterEach(async () => { + await deleteCases(es); + }); + + it('should return case tags', async () => { + await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq); + await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send({ ...postCaseReq, tags: ['unique'] }); + + const { body } = await supertest + .get(CASE_TAGS_URL) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + + expect(body).to.eql(['defacement', 'unique']); + }); + }); +}; diff --git a/x-pack/test/case_api_integration/basic/tests/cases/user_actions/get_all_user_actions.ts b/x-pack/test/case_api_integration/basic/tests/cases/user_actions/get_all_user_actions.ts new file mode 100644 index 0000000000000..6bbd43eef1439 --- /dev/null +++ b/x-pack/test/case_api_integration/basic/tests/cases/user_actions/get_all_user_actions.ts @@ -0,0 +1,307 @@ +/* + * 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, CASES_URL } from '../../../../../../plugins/case/common/constants'; +import { defaultUser, postCaseReq, postCommentReq } from '../../../../common/lib/mock'; +import { + deleteCases, + deleteCasesUserActions, + deleteComments, + deleteConfiguration, + getConfiguration, +} from '../../../../common/lib/utils'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext): void => { + const supertest = getService('supertest'); + const es = getService('es'); + + describe('get_all_user_actions', () => { + afterEach(async () => { + await deleteCases(es); + await deleteComments(es); + await deleteConfiguration(es); + await deleteCasesUserActions(es); + }); + + it(`on new case, user action: 'create' should be called with actionFields: ['description', 'status', 'tags', 'title']`, async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq); + + const { body } = await supertest + .get(`${CASES_URL}/${postedCase.id}/user_actions`) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + expect(body.length).to.eql(1); + + expect(body[0].action_field).to.eql(['description', 'status', 'tags', 'title']); + expect(body[0].action).to.eql('create'); + expect(body[0].old_value).to.eql(null); + expect(body[0].new_value).to.eql(JSON.stringify(postCaseReq)); + }); + + it(`on close case, user action: 'update' should be called with actionFields: ['status']`, async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq); + await supertest + .patch(CASES_URL) + .set('kbn-xsrf', 'true') + .send({ + cases: [ + { + id: postedCase.id, + version: postedCase.version, + status: 'closed', + }, + ], + }) + .expect(200); + + const { body } = await supertest + .get(`${CASES_URL}/${postedCase.id}/user_actions`) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + expect(body.length).to.eql(2); + expect(body[1].action_field).to.eql(['status']); + expect(body[1].action).to.eql('update'); + expect(body[1].old_value).to.eql('open'); + expect(body[1].new_value).to.eql('closed'); + }); + + it(`on update case connector, user action: 'update' should be called with actionFields: ['connector_id']`, async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq); + const newConnectorId = '12345'; + await supertest + .patch(CASES_URL) + .set('kbn-xsrf', 'true') + .send({ + cases: [ + { + id: postedCase.id, + version: postedCase.version, + connector_id: newConnectorId, + }, + ], + }) + .expect(200); + + const { body } = await supertest + .get(`${CASES_URL}/${postedCase.id}/user_actions`) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + expect(body.length).to.eql(2); + expect(body[1].action_field).to.eql(['connector_id']); + expect(body[1].action).to.eql('update'); + expect(body[1].old_value).to.eql('none'); + expect(body[1].new_value).to.eql(newConnectorId); + }); + + it(`on update tags, user action: 'add' and 'delete' should be called with actionFields: ['tags']`, async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq); + await supertest + .patch(CASES_URL) + .set('kbn-xsrf', 'true') + .send({ + cases: [ + { + id: postedCase.id, + version: postedCase.version, + tags: ['cool', 'neat'], + }, + ], + }) + .expect(200); + + const { body } = await supertest + .get(`${CASES_URL}/${postedCase.id}/user_actions`) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + expect(body.length).to.eql(3); + expect(body[1].action_field).to.eql(['tags']); + expect(body[1].action).to.eql('add'); + expect(body[1].old_value).to.eql(null); + expect(body[1].new_value).to.eql('cool, neat'); + expect(body[2].action_field).to.eql(['tags']); + expect(body[2].action).to.eql('delete'); + expect(body[2].old_value).to.eql(null); + expect(body[2].new_value).to.eql('defacement'); + }); + + it(`on update title, user action: 'update' should be called with actionFields: ['title']`, async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq); + const newTitle = 'Such a great title'; + await supertest + .patch(CASES_URL) + .set('kbn-xsrf', 'true') + .send({ + cases: [ + { + id: postedCase.id, + version: postedCase.version, + title: newTitle, + }, + ], + }) + .expect(200); + + const { body } = await supertest + .get(`${CASES_URL}/${postedCase.id}/user_actions`) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + expect(body.length).to.eql(2); + expect(body[1].action_field).to.eql(['title']); + expect(body[1].action).to.eql('update'); + expect(body[1].old_value).to.eql(postCaseReq.title); + expect(body[1].new_value).to.eql(newTitle); + }); + + it(`on update description, user action: 'update' should be called with actionFields: ['description']`, async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq); + const newDesc = 'Such a great description'; + await supertest + .patch(CASES_URL) + .set('kbn-xsrf', 'true') + .send({ + cases: [ + { + id: postedCase.id, + version: postedCase.version, + description: newDesc, + }, + ], + }) + .expect(200); + + const { body } = await supertest + .get(`${CASES_URL}/${postedCase.id}/user_actions`) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + expect(body.length).to.eql(2); + expect(body[1].action_field).to.eql(['description']); + expect(body[1].action).to.eql('update'); + expect(body[1].old_value).to.eql(postCaseReq.description); + expect(body[1].new_value).to.eql(newDesc); + }); + + it(`on new comment, user action: 'create' should be called with actionFields: ['comments']`, async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq); + await supertest + .post(`${CASES_URL}/${postedCase.id}/comments`) + .set('kbn-xsrf', 'true') + .send(postCommentReq); + + const { body } = await supertest + .get(`${CASES_URL}/${postedCase.id}/user_actions`) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + expect(body.length).to.eql(2); + + expect(body[1].action_field).to.eql(['comment']); + expect(body[1].action).to.eql('create'); + expect(body[1].old_value).to.eql(null); + expect(body[1].new_value).to.eql(postCommentReq.comment); + }); + + it(`on update comment, user action: 'update' should be called with actionFields: ['comments']`, async () => { + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq); + const { body: patchedCase } = await supertest + .post(`${CASES_URL}/${postedCase.id}/comments`) + .set('kbn-xsrf', 'true') + .send(postCommentReq); + const newComment = 'Well I decided to update my comment. So what? Deal with it.'; + await supertest + .patch(`${CASES_URL}/${postedCase.id}/comments`) + .set('kbn-xsrf', 'true') + .send({ + id: patchedCase.comments[0].id, + version: patchedCase.comments[0].version, + comment: newComment, + }); + + const { body } = await supertest + .get(`${CASES_URL}/${postedCase.id}/user_actions`) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + expect(body.length).to.eql(3); + + expect(body[2].action_field).to.eql(['comment']); + expect(body[2].action).to.eql('update'); + expect(body[2].old_value).to.eql(postCommentReq.comment); + expect(body[2].new_value).to.eql(newComment); + }); + + it(`on new push to service, user action: 'push-to-service' should be called with actionFields: ['pushed']`, async () => { + const { body: configure } = await supertest + .post(CASE_CONFIGURE_URL) + .set('kbn-xsrf', 'true') + .send(getConfiguration()) + .expect(200); + const { body: postedCase } = await supertest + .post(CASES_URL) + .set('kbn-xsrf', 'true') + .send(postCaseReq); + + await supertest + .post(`${CASES_URL}/${postedCase.id}/_push`) + .set('kbn-xsrf', 'true') + .send({ + connector_id: configure.connector_id, + connector_name: configure.connector_name, + external_id: 'external_id', + external_title: 'external_title', + external_url: 'external_url', + }) + .expect(200); + + const { body } = await supertest + .get(`${CASES_URL}/${postedCase.id}/user_actions`) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + expect(body.length).to.eql(2); + + expect(body[1].action_field).to.eql(['pushed']); + expect(body[1].action).to.eql('push-to-service'); + expect(body[1].old_value).to.eql(null); + const newValue = JSON.parse(body[1].new_value); + expect(newValue.connector_id).to.eql(configure.connector_id); + expect(newValue.pushed_by).to.eql(defaultUser); + }); + }); +}; diff --git a/x-pack/test/case_api_integration/basic/tests/index.ts b/x-pack/test/case_api_integration/basic/tests/index.ts index efd5369c019d8..b152a97a28616 100644 --- a/x-pack/test/case_api_integration/basic/tests/index.ts +++ b/x-pack/test/case_api_integration/basic/tests/index.ts @@ -12,9 +12,24 @@ export default ({ loadTestFile }: FtrProviderContext): void => { // Fastest ciGroup for the moment. this.tags('ciGroup2'); + loadTestFile(require.resolve('./cases/comments/delete_comment')); + loadTestFile(require.resolve('./cases/comments/find_comments')); + loadTestFile(require.resolve('./cases/comments/get_comment')); + loadTestFile(require.resolve('./cases/comments/patch_comment')); + loadTestFile(require.resolve('./cases/comments/post_comment')); + loadTestFile(require.resolve('./cases/delete_cases')); + loadTestFile(require.resolve('./cases/find_cases')); + loadTestFile(require.resolve('./cases/get_case')); + loadTestFile(require.resolve('./cases/patch_cases')); + loadTestFile(require.resolve('./cases/post_case')); + loadTestFile(require.resolve('./cases/push_case')); + loadTestFile(require.resolve('./cases/reporters/get_reporters')); + loadTestFile(require.resolve('./cases/status/get_status')); + loadTestFile(require.resolve('./cases/tags/get_tags')); + loadTestFile(require.resolve('./cases/user_actions/get_all_user_actions')); loadTestFile(require.resolve('./configure/get_configure')); - loadTestFile(require.resolve('./configure/post_configure')); - loadTestFile(require.resolve('./configure/patch_configure')); loadTestFile(require.resolve('./configure/get_connectors')); + loadTestFile(require.resolve('./configure/patch_configure')); + loadTestFile(require.resolve('./configure/post_configure')); }); }; diff --git a/x-pack/test/case_api_integration/common/lib/mock.ts b/x-pack/test/case_api_integration/common/lib/mock.ts new file mode 100644 index 0000000000000..728eaf88617e9 --- /dev/null +++ b/x-pack/test/case_api_integration/common/lib/mock.ts @@ -0,0 +1,50 @@ +/* + * 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 { + CasePostRequest, + CaseResponse, + CasesFindResponse, +} from '../../../../plugins/case/common/api'; +export const defaultUser = { email: null, full_name: null, username: 'elastic' }; +export const postCaseReq: CasePostRequest = { + description: 'This is a brand new case of a bad meanie defacing data', + title: 'Super Bad Security Issue', + tags: ['defacement'], +}; + +export const postCommentReq: { comment: string } = { + comment: 'This is a cool comment', +}; + +export const postCaseResp = (id: string): Partial => ({ + ...postCaseReq, + id, + comments: [], + totalComment: 0, + connector_id: 'none', + closed_by: null, + created_by: defaultUser, + external_service: null, + status: 'open', + updated_by: null, +}); + +export const removeServerGeneratedPropertiesFromCase = ( + config: Partial +): Partial => { + const { closed_at, created_at, updated_at, version, ...rest } = config; + return rest; +}; + +export const findCasesResp: CasesFindResponse = { + page: 1, + per_page: 20, + total: 0, + cases: [], + count_open_cases: 0, + count_closed_cases: 0, +}; diff --git a/x-pack/test/case_api_integration/common/lib/utils.ts b/x-pack/test/case_api_integration/common/lib/utils.ts index df768ff09b368..4b1dc6ffa5891 100644 --- a/x-pack/test/case_api_integration/common/lib/utils.ts +++ b/x-pack/test/case_api_integration/common/lib/utils.ts @@ -30,6 +30,36 @@ export const removeServerGeneratedPropertiesFromConfigure = ( return rest; }; +export const deleteCasesUserActions = async (es: Client): Promise => { + await es.deleteByQuery({ + index: '.kibana', + q: 'type:cases-user-actions', + wait_for_completion: true, + refresh: true, + body: {}, + }); +}; + +export const deleteCases = async (es: Client): Promise => { + await es.deleteByQuery({ + index: '.kibana', + q: 'type:cases', + wait_for_completion: true, + refresh: true, + body: {}, + }); +}; + +export const deleteComments = async (es: Client): Promise => { + await es.deleteByQuery({ + index: '.kibana', + q: 'type:cases-comments', + wait_for_completion: true, + refresh: true, + body: {}, + }); +}; + export const deleteConfiguration = async (es: Client): Promise => { await es.deleteByQuery({ index: '.kibana', @@ -39,34 +69,3 @@ export const deleteConfiguration = async (es: Client): Promise => { 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', - }, - ], - }, - }, -});