import type SuperTest from 'supertest' ; import type { Type , ListSchema , ListItemSchema , ExceptionListSchema , ExceptionListItemSchema , ExceptionList , } from '@kbn/securitysolution-io-ts-list-types' ; import { EXCEPTION_LIST_URL , LIST_INDEX , LIST_ITEM_URL , } from '@kbn/securitysolution-list-constants' ; import { ToolingLog } from '@kbn/dev-utils' ; import { getImportListItemAsBuffer } from '../../plugins/lists/common/schemas/request/import_list_item_schema.mock' ; import { countDownTest } from '../detection_engine_api_integration/utils' ; param supertest export const createListsIndex = async ( supertest , log ) : Promise < void > => { return countDownTest ( async ( ) => { await supertest . post ( LIST_INDEX ) . set ( 'kbn-xsrf' , 'true' ) . send ( ) ; return true ; } , 'createListsIndex' , log ) ; } ; param supertest export const deleteListsIndex = async ( supertest , log ) : Promise < void > => { return countDownTest ( async ( ) => { await supertest . delete ( LIST_INDEX ) . set ( 'kbn-xsrf' , 'true' ) . send ( ) ; return true ; } , 'deleteListsIndex' , log ) ; } ; param supertest export const createExceptionListsIndex = async ( supertest , log ) : Promise < void > => { return countDownTest ( async ( ) => { await supertest . post ( LIST_INDEX ) . set ( 'kbn-xsrf' , 'true' ) . send ( ) ; return true ; } , 'createListsIndex' , log ) ; } ; param list export const removeListServerGeneratedProperties = ( list ) : Partial < ListSchema > => { const { created_at , updated_at , id , tie_breaker_id , _version , ... removedProperties } = list ; return removedProperties ; } ; param list export const removeListItemServerGeneratedProperties = ( list ) : Partial < ListItemSchema > => { const { created_at , updated_at , id , tie_breaker_id , _version , ... removedProperties } = list ; return removedProperties ; } ; param list export const removeExceptionListItemServerGeneratedProperties = ( list ) : Partial < ExceptionListItemSchema > => { const { created_at , updated_at , id , tie_breaker_id , _version , ... removedProperties } = list ; return removedProperties ; } ; param list export const removeExceptionListServerGeneratedProperties = ( list ) : Partial < ExceptionListSchema > => { const { created_at , updated_at , id , tie_breaker_id , _version , ... removedProperties } = list ; return removedProperties ; } ; export const waitFor = async ( functionToTest , functionName , log , maxTimeout = 800000 , timeoutWait = 250 ) => { await new Promise < void > ( async ( resolve , reject ) => { try { let found = false ; let numberOfTries = 0 ; const maxTries = Math . floor ( maxTimeout / timeoutWait ) ; while ( ! found && numberOfTries < maxTries ) { const itPasses = await functionToTest ( ) ; if ( itPasses ) { found = true ; } else { log . debug ( `Try number ${ numberOfTries } out of ${ maxTries } for function ${ functionName }` ) ; numberOfTries ++ ; } await new Promise ( ( resolveTimeout ) => setTimeout ( resolveTimeout , timeoutWait ) ) ; } if ( found ) { resolve ( ) ; } else { reject ( new Error ( `timed out waiting for function ${ functionName } condition to be true` ) ) ; } } catch ( error ) { reject ( error ) ; } } ) ; } ; param res param callback export const binaryToString = ( res , callback ) : void => { res . setEncoding ( 'binary' ) ; res . data = '' ; res . on ( 'data' , ( chunk ) => { res . data += chunk ; } ) ; res . on ( 'end' , ( ) => { callback ( null , Buffer . from ( res . data ) ) ; } ) ; } ; param supertest export const deleteAllExceptions = async ( supertest , log ) : Promise < void > => { await countDownTest ( async ( ) => { const { body } = await supertest . get ( `${ EXCEPTION_LIST_URL }/_find?per_page=9999` ) . set ( 'kbn-xsrf' , 'true' ) . send ( ) ; const ids = body . data . map ( ( exception ) => exception . id ) ; for await ( const id of ids ) { await supertest . delete ( `${ EXCEPTION_LIST_URL }?id=${ id }` ) . set ( 'kbn-xsrf' , 'true' ) . send ( ) ; } const { body : finalCheck } = await supertest . get ( `${ EXCEPTION_LIST_URL }/_find` ) . set ( 'kbn-xsrf' , 'true' ) . send ( ) ; return finalCheck . data . length === 0 ; } , 'deleteAllExceptions' , log , 50 , 1000 ) ; } ; param supertest param type param contents param fileName param testValues export const importFile = async ( supertest , log , type , contents , fileName , testValues ? ) : Promise < void > => { const response = await supertest . post ( `${ LIST_ITEM_URL }/_import?type=${ type }` ) . set ( 'kbn-xsrf' , 'true' ) . attach ( 'file' , getImportListItemAsBuffer ( contents ) , fileName ) . expect ( 'Content-Type' , 'application/json; charset=utf-8' ) ; if ( response . status !== 200 ) { log . error ( `Did not get an expected 200 "ok" When importing a file (importFile). CI issues could happen. Suspect this line if you are seeing CI issues. body: ${ JSON . stringify ( response . body ) }, status: ${ JSON . stringify ( response . status ) }` ) ; } const testValuesOrContents = testValues ?? contents ; await waitForListItems ( supertest , log , testValuesOrContents , fileName ) ; } ; param supertest param type param contents param fileName export const importTextFile = async ( supertest , log , type , contents , fileName ) : Promise < void > => { const response = await supertest . post ( `${ LIST_ITEM_URL }/_import?type=${ type }` ) . set ( 'kbn-xsrf' , 'true' ) . attach ( 'file' , getImportListItemAsBuffer ( contents ) , fileName ) . expect ( 'Content-Type' , 'application/json; charset=utf-8' ) ; if ( response . status !== 200 ) { log . error ( `Did not get an expected 200 "ok" when importing a text file (importTextFile). CI issues could happen. Suspect this line if you are seeing CI issues. body: ${ JSON . stringify ( response . body ) }, status: ${ JSON . stringify ( response . status ) }` ) ; } await waitForTextListItems ( supertest , log , contents , fileName ) ; } ; param supertest param fileName param itemValue export const waitForListItem = async ( supertest , log , itemValue , fileName ) : Promise < void > => { await waitFor ( async ( ) => { const { status , body } = await supertest . get ( `${ LIST_ITEM_URL }?list_id=${ fileName }&value=${ itemValue }` ) . send ( ) ; if ( status !== 200 ) { log . debug ( `Did not get an expected 200 "ok" when waiting for a list item (waitForListItem) yet. Retrying until we get a 200 "ok". body: ${ JSON . stringify ( body ) }, status: ${ JSON . stringify ( status ) }` ) ; } return status === 200 ; } , `waitForListItem fileName: "${ fileName }" itemValue: "${ itemValue }"` , log ) ; } ; param supertest param fileName param itemValue export const waitForListItems = async ( supertest , log , itemValues , fileName ) : Promise < void > => { await Promise . all ( itemValues . map ( ( item ) => waitForListItem ( supertest , log , item , fileName ) ) ) ; } ; param supertest param fileName param itemValue export const waitForTextListItem = async ( supertest , log , itemValue , fileName ) : Promise < void > => { const tokens = itemValue . split ( ' ' ) ; await waitFor ( async ( ) => { const promises = await Promise . all ( tokens . map ( async ( token ) => { const { status , body } = await supertest . get ( `${ LIST_ITEM_URL }?list_id=${ fileName }&value=${ token }` ) . send ( ) ; if ( status !== 200 ) { log . error ( `Did not get an expected 200 "ok" when waiting for a text list item (waitForTextListItem) yet. Retrying until we get a 200 "ok". body: ${ JSON . stringify ( body ) }, status: ${ JSON . stringify ( status ) }` ) ; } return status === 200 ; } ) ) ; return promises . every ( ( one ) => one ) ; } , `waitForTextListItem fileName: "${ fileName }" itemValue: "${ itemValue }"` , log ) ; } ; param supertest param fileName param itemValue export const waitForTextListItems = async ( supertest , log , itemValues , fileName ) : Promise < void > => { await Promise . all ( itemValues . map ( ( item ) => waitForTextListItem ( supertest , log , item , fileName ) ) ) ; } ;