import expect from '@kbn/expect' ; import { FtrProviderContext } from '../../../../common/ftr_provider_context' ; import { findSubCasesResp , postCollectionReq } from '../../../../common/lib/mock' ; import { createCaseAction , createSubCase , CreateSubCaseResp , deleteAllCaseItems , deleteCaseAction , setStatus , } from '../../../../common/lib/utils' ; import { getSubCasesUrl } from '../../../../../../plugins/cases/common/api/helpers' ; import { CaseResponse , CaseStatuses , CommentType , SubCasesFindResponse , } from '../../../../../../plugins/cases/common/api' ; import { CASES_URL } from '../../../../../../plugins/cases/common/constants' ; import { ContextTypeGeneratedAlertType , createAlertsString , } from '../../../../../../plugins/cases/server/connectors' ; interface SubCaseAttributes { 'cases-sub-case' : { created_at : string ; } ; } export default ( { getService } ) : void => { const supertest = getService ( 'supertest' ) ; const es = getService ( 'es' ) ; describe ( 'find_sub_cases disabled route' , ( ) => { it ( 'should return a 404 when attempting to access the route and the case connector feature is disabled' , async ( ) => { await supertest . get ( `${ getSubCasesUrl ( 'case-id' ) }/_find` ) . expect ( 404 ) ; } ) ; describe . skip ( 'create case connector' , ( ) => { let actionID ; before ( async ( ) => { actionID = await createCaseAction ( supertest ) ; } ) ; after ( async ( ) => { await deleteCaseAction ( supertest , actionID ) ; } ) ; describe ( 'basic find tests' , ( ) => { afterEach ( async ( ) => { await deleteAllCaseItems ( es ) ; } ) ; it ( 'should not find any sub cases when none exist' , async ( ) => { const { body : caseResp } = await supertest . post ( CASES_URL ) . set ( 'kbn-xsrf' , 'true' ) . send ( postCollectionReq ) . expect ( 200 ) ; const { body : findSubCases } = await supertest . get ( `${ getSubCasesUrl ( caseResp . id ) }/_find` ) . expect ( 200 ) ; expect ( findSubCases ) . to . eql ( { page : 1 , per_page : 20 , total : 0 , subCases : [ ] , count_open_cases : 0 , count_closed_cases : 0 , count_in_progress_cases : 0 , } ) ; } ) ; it ( 'should return a sub cases with comment stats' , async ( ) => { const { newSubCaseInfo : caseInfo } = await createSubCase ( { supertest , actionID } ) ; const { body } = await supertest . get ( `${ getSubCasesUrl ( caseInfo . id ) }/_find` ) . expect ( 200 ) ; expect ( body ) . to . eql ( { ... findSubCasesResp , total : 1 , subCases : [ { ... caseInfo . subCases ! [ 0 ] , comments : [ ] , totalComment : 1 , totalAlerts : 2 } ] , count_open_cases : 1 , } ) ; } ) ; it ( 'should return multiple sub cases' , async ( ) => { const { newSubCaseInfo : caseInfo } = await createSubCase ( { supertest , actionID } ) ; const subCase2Resp = await createSubCase ( { supertest , caseID : caseInfo . id , actionID } ) ; const { body } = await supertest . get ( `${ getSubCasesUrl ( caseInfo . id ) }/_find` ) . expect ( 200 ) ; expect ( body ) . to . eql ( { ... findSubCasesResp , total : 2 , subCases : [ { ... subCase2Resp . modifiedSubCases ! [ 0 ] , comments : [ ] , totalComment : 1 , totalAlerts : 2 , status : CaseStatuses . closed , } , { ... subCase2Resp . newSubCaseInfo . subCases ! [ 0 ] , comments : [ ] , totalComment : 1 , totalAlerts : 2 , } , ] , count_open_cases : 1 , count_closed_cases : 1 , } ) ; } ) ; it ( 'should only return open when filtering for open' , async ( ) => { const { newSubCaseInfo : caseInfo } = await createSubCase ( { supertest , actionID } ) ; await createSubCase ( { supertest , caseID : caseInfo . id , actionID } ) ; const { body } = await supertest . get ( `${ getSubCasesUrl ( caseInfo . id ) }/_find?status=${ CaseStatuses . open }` ) . expect ( 200 ) ; expect ( body . total ) . to . be ( 1 ) ; expect ( body . subCases [ 0 ] . status ) . to . be ( CaseStatuses . open ) ; expect ( body . count_closed_cases ) . to . be ( 1 ) ; expect ( body . count_open_cases ) . to . be ( 1 ) ; expect ( body . count_in_progress_cases ) . to . be ( 0 ) ; } ) ; it ( 'should only return closed when filtering for closed' , async ( ) => { const { newSubCaseInfo : caseInfo } = await createSubCase ( { supertest , actionID } ) ; await createSubCase ( { supertest , caseID : caseInfo . id , actionID } ) ; const { body } = await supertest . get ( `${ getSubCasesUrl ( caseInfo . id ) }/_find?status=${ CaseStatuses . closed }` ) . expect ( 200 ) ; expect ( body . total ) . to . be ( 1 ) ; expect ( body . subCases [ 0 ] . status ) . to . be ( CaseStatuses . closed ) ; expect ( body . count_closed_cases ) . to . be ( 1 ) ; expect ( body . count_open_cases ) . to . be ( 1 ) ; expect ( body . count_in_progress_cases ) . to . be ( 0 ) ; } ) ; it ( 'should only return in progress when filtering for in progress' , async ( ) => { const { newSubCaseInfo : caseInfo } = await createSubCase ( { supertest , actionID } ) ; const { newSubCaseInfo : secondSub } = await createSubCase ( { supertest , caseID : caseInfo . id , actionID , } ) ; await setStatus ( { supertest , cases : [ { id : secondSub . subCases ! [ 0 ] . id , version : secondSub . subCases ! [ 0 ] . version , status : CaseStatuses [ 'in-progress' ] , } , ] , type : 'sub_case' , } ) ; const { body } = await supertest . get ( `${ getSubCasesUrl ( caseInfo . id ) }/_find?status=${ CaseStatuses [ 'in-progress' ] }` ) . expect ( 200 ) ; expect ( body . total ) . to . be ( 1 ) ; expect ( body . subCases [ 0 ] . status ) . to . be ( CaseStatuses [ 'in-progress' ] ) ; expect ( body . count_closed_cases ) . to . be ( 1 ) ; expect ( body . count_open_cases ) . to . be ( 0 ) ; expect ( body . count_in_progress_cases ) . to . be ( 1 ) ; } ) ; it ( 'should sort on createdAt field in descending order' , async ( ) => { const { newSubCaseInfo : caseInfo } = await createSubCase ( { supertest , actionID } ) ; await createSubCase ( { supertest , caseID : caseInfo . id , actionID , } ) ; const { body } = await supertest . get ( `${ getSubCasesUrl ( caseInfo . id ) }/_find?sortField=createdAt&sortOrder=desc` ) . expect ( 200 ) ; expect ( body . total ) . to . be ( 2 ) ; expect ( body . subCases [ 0 ] . status ) . to . be ( CaseStatuses . open ) ; expect ( body . subCases [ 1 ] . status ) . to . be ( CaseStatuses . closed ) ; expect ( body . count_closed_cases ) . to . be ( 1 ) ; expect ( body . count_open_cases ) . to . be ( 1 ) ; expect ( body . count_in_progress_cases ) . to . be ( 0 ) ; } ) ; it ( 'should sort on createdAt field in ascending order' , async ( ) => { const { newSubCaseInfo : caseInfo } = await createSubCase ( { supertest , actionID } ) ; await createSubCase ( { supertest , caseID : caseInfo . id , actionID , } ) ; const { body } = await supertest . get ( `${ getSubCasesUrl ( caseInfo . id ) }/_find?sortField=createdAt&sortOrder=asc` ) . expect ( 200 ) ; expect ( body . total ) . to . be ( 2 ) ; expect ( body . subCases [ 0 ] . status ) . to . be ( CaseStatuses . closed ) ; expect ( body . subCases [ 1 ] . status ) . to . be ( CaseStatuses . open ) ; expect ( body . count_closed_cases ) . to . be ( 1 ) ; expect ( body . count_open_cases ) . to . be ( 1 ) ; expect ( body . count_in_progress_cases ) . to . be ( 0 ) ; } ) ; it ( 'should sort on updatedAt field in ascending order' , async ( ) => { const { newSubCaseInfo : caseInfo } = await createSubCase ( { supertest , actionID } ) ; const { newSubCaseInfo : secondSub } = await createSubCase ( { supertest , caseID : caseInfo . id , actionID , } ) ; await setStatus ( { supertest , cases : [ { id : secondSub . subCases ! [ 0 ] . id , version : secondSub . subCases ! [ 0 ] . version , status : CaseStatuses [ 'in-progress' ] , } , ] , type : 'sub_case' , } ) ; const { body } = await supertest . get ( `${ getSubCasesUrl ( caseInfo . id ) }/_find?sortField=updatedAt&sortOrder=asc` ) . expect ( 200 ) ; expect ( body . total ) . to . be ( 2 ) ; expect ( body . subCases [ 0 ] . status ) . to . be ( CaseStatuses . closed ) ; expect ( body . subCases [ 1 ] . status ) . to . be ( CaseStatuses [ 'in-progress' ] ) ; expect ( body . count_closed_cases ) . to . be ( 1 ) ; expect ( body . count_open_cases ) . to . be ( 0 ) ; expect ( body . count_in_progress_cases ) . to . be ( 1 ) ; } ) ; } ) ; describe ( 'pagination' , ( ) => { const numCases = 4 ; let collection ; before ( async ( ) => { ( { body : collection } = await supertest . post ( CASES_URL ) . set ( 'kbn-xsrf' , 'true' ) . send ( postCollectionReq ) . expect ( 200 ) ) ; await createSubCases ( numCases , collection . id ) ; } ) ; after ( async ( ) => { await deleteAllCaseItems ( es ) ; } ) ; const createSubCases = async ( total , caseID ) => { const responses = [ ] ; for ( let i = 0 ; i < total ; i ++ ) { const postCommentGenAlertReq = { alerts : createAlertsString ( [ { _id : `${ i }` , _index : 'test-index' , ruleId : 'rule-id' , ruleName : 'rule name' } , ] ) , type : CommentType . generatedAlert , owner : 'securitySolutionFixture' , } ; responses . push ( await createSubCase ( { supertest , actionID , caseID , comment : postCommentGenAlertReq , } ) ) ; } return responses ; } ; const getAllCasesSortedByCreatedAtAsc = async ( ) => { const cases = await es . search < SubCaseAttributes > ( { index : '.kibana' , body : { size : 10000 , sort : [ { 'cases-sub-case.created_at' : { unmapped_type : 'date' , order : 'asc' } } ] , query : { term : { type : 'cases-sub-case' } , } , } , } ) ; return cases . hits . hits . map ( ( hit ) => hit . _source ) ; } ; it ( 'returns the correct total when perPage is less than the total' , async ( ) => { const { body } = await supertest . get ( `${ getSubCasesUrl ( collection . id ) }/_find` ) . query ( { sortOrder : 'asc' , page : 1 , perPage : 3 , } ) . set ( 'kbn-xsrf' , 'true' ) . expect ( 200 ) ; expect ( body . subCases . length ) . to . eql ( 3 ) ; expect ( body . total ) . to . eql ( 4 ) ; expect ( body . page ) . to . eql ( 1 ) ; expect ( body . per_page ) . to . eql ( 3 ) ; expect ( body . count_open_cases ) . to . eql ( 1 ) ; expect ( body . count_closed_cases ) . to . eql ( 3 ) ; expect ( body . count_in_progress_cases ) . to . eql ( 0 ) ; } ) ; it ( 'returns the correct total when perPage is greater than the total' , async ( ) => { const { body } = await supertest . get ( `${ getSubCasesUrl ( collection . id ) }/_find` ) . query ( { sortOrder : 'asc' , page : 1 , perPage : 11 , } ) . set ( 'kbn-xsrf' , 'true' ) . expect ( 200 ) ; expect ( body . total ) . to . eql ( 4 ) ; expect ( body . page ) . to . eql ( 1 ) ; expect ( body . per_page ) . to . eql ( 11 ) ; expect ( body . subCases . length ) . to . eql ( 4 ) ; expect ( body . count_open_cases ) . to . eql ( 1 ) ; expect ( body . count_closed_cases ) . to . eql ( 3 ) ; expect ( body . count_in_progress_cases ) . to . eql ( 0 ) ; } ) ; it ( 'returns the correct total when perPage is equal to the total' , async ( ) => { const { body } = await supertest . get ( `${ getSubCasesUrl ( collection . id ) }/_find` ) . query ( { sortOrder : 'asc' , page : 1 , perPage : 4 , } ) . set ( 'kbn-xsrf' , 'true' ) . expect ( 200 ) ; expect ( body . total ) . to . eql ( 4 ) ; expect ( body . page ) . to . eql ( 1 ) ; expect ( body . per_page ) . to . eql ( 4 ) ; expect ( body . subCases . length ) . to . eql ( 4 ) ; expect ( body . count_open_cases ) . to . eql ( 1 ) ; expect ( body . count_closed_cases ) . to . eql ( 3 ) ; expect ( body . count_in_progress_cases ) . to . eql ( 0 ) ; } ) ; it ( 'returns the second page of results' , async ( ) => { const perPage = 2 ; const { body } = await supertest . get ( `${ getSubCasesUrl ( collection . id ) }/_find` ) . query ( { sortOrder : 'asc' , page : 2 , perPage , } ) . set ( 'kbn-xsrf' , 'true' ) . expect ( 200 ) ; expect ( body . total ) . to . eql ( 4 ) ; expect ( body . page ) . to . eql ( 2 ) ; expect ( body . per_page ) . to . eql ( 2 ) ; expect ( body . subCases . length ) . to . eql ( 2 ) ; expect ( body . count_open_cases ) . to . eql ( 1 ) ; expect ( body . count_closed_cases ) . to . eql ( 3 ) ; expect ( body . count_in_progress_cases ) . to . eql ( 0 ) ; const allCases = await getAllCasesSortedByCreatedAtAsc ( ) ; body . subCases . map ( ( subCaseInfo , index ) => { expect ( subCaseInfo . created_at ) . to . eql ( allCases [ index + perPage ] ?. [ 'cases-sub-case' ] . created_at ) ; } ) ; } ) ; it ( 'paginates with perPage of 2 through 4 total sub cases' , async ( ) => { const total = 4 ; const perPage = 2 ; for ( let currentPage = 1 ; currentPage <= total / perPage ; currentPage ++ ) { const { body } = await supertest . get ( `${ getSubCasesUrl ( collection . id ) }/_find` ) . query ( { sortOrder : 'asc' , page : currentPage , perPage , } ) . set ( 'kbn-xsrf' , 'true' ) . expect ( 200 ) ; expect ( body . total ) . to . eql ( total ) ; expect ( body . page ) . to . eql ( currentPage ) ; expect ( body . per_page ) . to . eql ( perPage ) ; expect ( body . subCases . length ) . to . eql ( perPage ) ; expect ( body . count_open_cases ) . to . eql ( 1 ) ; expect ( body . count_closed_cases ) . to . eql ( total - 1 ) ; expect ( body . count_in_progress_cases ) . to . eql ( 0 ) ; const allCases = await getAllCasesSortedByCreatedAtAsc ( ) ; body . subCases . map ( ( subCaseInfo , index ) => { expect ( subCaseInfo . created_at ) . to . eql ( allCases [ index + perPage * ( currentPage - 1 ) ] ?. [ 'cases-sub-case' ] . created_at ) ; } ) ; } } ) ; it ( 'retrieves the last sub case' , async ( ) => { const { body } = await supertest . get ( `${ getSubCasesUrl ( collection . id ) }/_find` ) . query ( { sortOrder : 'asc' , page : 2 , perPage : 3 , } ) . set ( 'kbn-xsrf' , 'true' ) . expect ( 200 ) ; expect ( body . total ) . to . eql ( 4 ) ; expect ( body . page ) . to . eql ( 2 ) ; expect ( body . per_page ) . to . eql ( 3 ) ; expect ( body . subCases . length ) . to . eql ( 1 ) ; expect ( body . count_open_cases ) . to . eql ( 1 ) ; expect ( body . count_closed_cases ) . to . eql ( 3 ) ; expect ( body . count_in_progress_cases ) . to . eql ( 0 ) ; } ) ; } ) ; } ) ; } ) ; } ;