import expect from '@kbn/expect' ; import { FtrProviderContext } from '../../ftr_provider_context' ; type TransformRowActionName = 'Clone' | 'Delete' | 'Edit' | 'Start' | 'Stop' | 'Discover' ; export function TransformTableProvider ( { getService } ) { const find = getService ( 'find' ) ; const retry = getService ( 'retry' ) ; const testSubjects = getService ( 'testSubjects' ) ; const browser = getService ( 'browser' ) ; return new ( class TransformTable { public async parseTransformTable ( ) { const table = await testSubjects . find ( '~transformListTable' ) ; const $ = await table . parseDomContent ( ) ; const rows = [ ] ; for ( const tr of $ . findTestSubjects ( '~transformListRow' ) . toArray ( ) ) { const $tr = $ ( tr ) ; rows . push ( { id : $tr . findTestSubject ( 'transformListColumnId' ) . find ( '.euiTableCellContent' ) . text ( ) . trim ( ) , description : $tr . findTestSubject ( 'transformListColumnDescription' ) . find ( '.euiTableCellContent' ) . text ( ) . trim ( ) , type : $tr . findTestSubject ( 'transformListColumnType' ) . find ( '.euiTableCellContent' ) . text ( ) . trim ( ) , status : $tr . findTestSubject ( 'transformListColumnStatus' ) . find ( '.euiTableCellContent' ) . text ( ) . trim ( ) , mode : $tr . findTestSubject ( 'transformListColumnMode' ) . find ( '.euiTableCellContent' ) . text ( ) . trim ( ) , progress : $tr . findTestSubject ( 'transformListColumnProgress' ) . findTestSubject ( 'transformListProgress' ) . attr ( 'value' ) , } ) ; } return rows ; } async parseEuiDataGrid ( tableSubj ) { const table = await testSubjects . find ( `~${ tableSubj }` ) ; const $ = await table . parseDomContent ( ) ; const rows = [ ] ; for ( const tr of $ . findTestSubjects ( `~dataGridRow` ) . toArray ( ) ) { rows . push ( $ ( tr ) . find ( '.euiDataGridRowCell__truncate' ) . toArray ( ) . map ( ( cell ) => $ ( cell ) . text ( ) . trim ( ) ) ) ; } return rows ; } async assertEuiDataGridColumnValues ( tableSubj , column , expectedColumnValues ) { await retry . tryForTime ( 2000 , async ( ) => { const rows = await this . parseEuiDataGrid ( tableSubj ) ; const uniqueColumnValues = rows . map ( ( row ) => row [ column ] ) . flat ( ) . filter ( ( v , i , a ) => a . indexOf ( v ) === i ) ; uniqueColumnValues . sort ( ) ; expect ( uniqueColumnValues ) . to . eql ( expectedColumnValues , `Expected '${ tableSubj }' column values to be '${ expectedColumnValues }' (got '${ uniqueColumnValues }')` ) ; } ) ; } public async waitForRefreshButtonLoaded ( ) { await testSubjects . existOrFail ( '~transformRefreshTransformListButton' , { timeout : 10 * 1000 , } ) ; await testSubjects . existOrFail ( 'transformRefreshTransformListButton loaded' , { timeout : 30 * 1000 , } ) ; } public async refreshTransformList ( ) { await this . waitForRefreshButtonLoaded ( ) ; await testSubjects . click ( '~transformRefreshTransformListButton' ) ; await this . waitForRefreshButtonLoaded ( ) ; await this . waitForTransformsToLoad ( ) ; } public async waitForTransformsToLoad ( ) { await testSubjects . existOrFail ( '~transformListTable' , { timeout : 60 * 1000 } ) ; await testSubjects . existOrFail ( 'transformListTable loaded' , { timeout : 30 * 1000 } ) ; } public async filterWithSearchString ( filter , expectedRowCount = 1 ) { await this . waitForTransformsToLoad ( ) ; const tableListContainer = await testSubjects . find ( 'transformListTableContainer' ) ; const searchBarInput = await tableListContainer . findByClassName ( 'euiFieldSearch' ) ; await searchBarInput . clearValueWithKeyboard ( ) ; await searchBarInput . type ( filter ) ; const rows = await this . parseTransformTable ( ) ; const filteredRows = rows . filter ( ( row ) => row . id === filter ) ; expect ( filteredRows ) . to . have . length ( expectedRowCount , `Filtered Transform table should have ${ expectedRowCount } row(s) for filter '${ filter }' (got matching items '${ filteredRows }')` ) ; } public async clearSearchString ( expectedRowCount = 1 ) { await this . waitForTransformsToLoad ( ) ; const tableListContainer = await testSubjects . find ( 'transformListTableContainer' ) ; const searchBarInput = await tableListContainer . findByClassName ( 'euiFieldSearch' ) ; await searchBarInput . clearValueWithKeyboard ( ) ; const rows = await this . parseTransformTable ( ) ; expect ( rows ) . to . have . length ( expectedRowCount , `Transform table should have ${ expectedRowCount } row(s) after clearing search' (got '${ rows . length }')` ) ; } public async assertTransformRowFields ( transformId , expectedRow ) { await retry . tryForTime ( 30 * 1000 , async ( ) => { await this . refreshTransformList ( ) ; const rows = await this . parseTransformTable ( ) ; const transformRow = rows . filter ( ( row ) => row . id === transformId ) [ 0 ] ; expect ( transformRow ) . to . eql ( expectedRow , `Expected transform row to be '${ JSON . stringify ( expectedRow ) }' (got '${ JSON . stringify ( transformRow ) }')` ) ; } ) ; } public async assertTransformRowProgressGreaterThan ( transformId , expectedProgress ) { await retry . tryForTime ( 30 * 1000 , async ( ) => { await this . refreshTransformList ( ) ; const rows = await this . parseTransformTable ( ) ; const transformRow = rows . filter ( ( row ) => row . id === transformId ) [ 0 ] ; expect ( transformRow . progress ) . to . greaterThan ( 0 , `Expected transform row progress to be greater than '${ expectedProgress }' (got '${ transformRow . progress }')` ) ; } ) ; } public async assertTransformRowStatusNotEql ( transformId , status ) { await retry . tryForTime ( 30 * 1000 , async ( ) => { await this . refreshTransformList ( ) ; const rows = await this . parseTransformTable ( ) ; const transformRow = rows . filter ( ( row ) => row . id === transformId ) [ 0 ] ; expect ( transformRow . status ) . to . not . eql ( status , `Expected transform row status to not be '${ status }' (got '${ transformRow . status }')` ) ; } ) ; } public async ensureDetailsOpen ( ) { await retry . tryForTime ( 30 * 1000 , async ( ) => { if ( ! ( await testSubjects . exists ( 'transformExpandedRowTabbedContent' ) ) ) { await testSubjects . click ( 'transformListRowDetailsToggle' ) ; await testSubjects . existOrFail ( 'transformExpandedRowTabbedContent' , { timeout : 1000 } ) ; } } ) ; } public async ensureDetailsClosed ( ) { await retry . tryForTime ( 30 * 1000 , async ( ) => { if ( await testSubjects . exists ( 'transformExpandedRowTabbedContent' ) ) { await testSubjects . click ( 'transformListRowDetailsToggle' ) ; await testSubjects . missingOrFail ( 'transformExpandedRowTabbedContent' , { timeout : 1000 } ) ; } } ) ; } public async switchToExpandedRowTab ( tabSubject , contentSubject ) { await retry . tryForTime ( 30 * 1000 , async ( ) => { await testSubjects . click ( tabSubject ) ; await testSubjects . existOrFail ( contentSubject , { timeout : 1000 } ) ; } ) ; } public async assertTransformExpandedRow ( ) { await this . ensureDetailsOpen ( ) ; await retry . tryForTime ( 30 * 1000 , async ( ) => { await testSubjects . existOrFail ( 'transformDetailsTab' , { timeout : 1000 } ) ; await testSubjects . existOrFail ( '~transformDetailsTabContent' , { timeout : 1000 } ) ; } ) ; await this . switchToExpandedRowTab ( 'transformJsonTab' , '~transformJsonTabContent' ) ; await this . switchToExpandedRowTab ( 'transformMessagesTab' , '~transformMessagesTabContent' ) ; await this . switchToExpandedRowTab ( 'transformPreviewTab' , '~transformPivotPreview' ) ; } public async assertTransformExpandedRowMessages ( expectedText ) { await this . ensureDetailsOpen ( ) ; await testSubjects . existOrFail ( 'transformDetailsTab' ) ; await testSubjects . existOrFail ( '~transformDetailsTabContent' ) ; await this . switchToExpandedRowTab ( 'transformMessagesTab' , '~transformMessagesTabContent' ) ; await retry . tryForTime ( 30 * 1000 , async ( ) => { const actualText = await testSubjects . getVisibleText ( '~transformMessagesTabContent' ) ; expect ( actualText . toLowerCase ( ) ) . to . contain ( expectedText . toLowerCase ( ) , `Expected transform messages text to include '${ expectedText }'` ) ; } ) ; } public rowSelector ( transformId , subSelector ? ) { const row = `~transformListTable > ~row-${ transformId }` ; return ! subSelector ? row : `${ row } > ${ subSelector }` ; } public async ensureTransformActionsMenuOpen ( transformId ) { await retry . tryForTime ( 30 * 1000 , async ( ) => { await this . ensureTransformActionsMenuClosed ( ) ; if ( ! ( await find . existsByCssSelector ( '.euiContextMenuPanel' , 1000 ) ) ) { await testSubjects . click ( this . rowSelector ( transformId , 'euiCollapsedItemActionsButton' ) ) ; expect ( await find . existsByCssSelector ( '.euiContextMenuPanel' , 1000 ) ) . to . eql ( true , 'Actions popover should exist' ) ; } } ) ; } public async ensureTransformActionsMenuClosed ( ) { await retry . tryForTime ( 30 * 1000 , async ( ) => { await browser . pressKeys ( browser . keys . ESCAPE ) ; expect ( await find . existsByCssSelector ( '.euiContextMenuPanel' , 1000 ) ) . to . eql ( false , 'Actions popover should not exist' ) ; } ) ; } public async assertTransformRowActionsButtonEnabled ( transformId , expectedValue ) { const isEnabled = await testSubjects . isEnabled ( this . rowSelector ( transformId , 'euiCollapsedItemActionsButton' ) ) ; expect ( isEnabled ) . to . eql ( expectedValue , `Expected transform row actions button to be '${ expectedValue ? 'enabled' : 'disabled' }' (got '${ isEnabled ? 'enabled' : 'disabled' }')` ) ; } public async assertTransformRowActions ( transformId , isTransformRunning = false ) { await this . ensureTransformActionsMenuOpen ( transformId ) ; await testSubjects . existOrFail ( 'transformActionClone' ) ; await testSubjects . existOrFail ( 'transformActionDelete' ) ; await testSubjects . existOrFail ( 'transformActionDiscover' ) ; await testSubjects . existOrFail ( 'transformActionEdit' ) ; if ( isTransformRunning ) { await testSubjects . missingOrFail ( 'transformActionStart' ) ; await testSubjects . existOrFail ( 'transformActionStop' ) ; } else { await testSubjects . existOrFail ( 'transformActionStart' ) ; await testSubjects . missingOrFail ( 'transformActionStop' ) ; } await this . ensureTransformActionsMenuClosed ( ) ; } public async assertTransformRowActionEnabled ( transformId , action , expectedValue ) { const selector = `transformAction${ action }` ; await retry . tryForTime ( 60 * 1000 , async ( ) => { await this . refreshTransformList ( ) ; await this . ensureTransformActionsMenuOpen ( transformId ) ; await testSubjects . existOrFail ( selector , { timeout : 1000 } ) ; const isEnabled = await testSubjects . isEnabled ( selector ) ; expect ( isEnabled ) . to . eql ( expectedValue , `Expected '${ action }' button to be '${ expectedValue ? 'enabled' : 'disabled' }' (got '${ isEnabled ? 'enabled' : 'disabled' }')` ) ; await this . ensureTransformActionsMenuClosed ( ) ; } ) ; } public async clickTransformRowAction ( transformId , action ) { await this . ensureTransformActionsMenuOpen ( transformId ) ; await testSubjects . click ( `transformAction${ action }` ) ; await testSubjects . missingOrFail ( `transformAction${ action }` ) ; } public async waitForTransformsExpandedRowPreviewTabToLoad ( ) { await testSubjects . existOrFail ( '~transformPivotPreview' , { timeout : 60 * 1000 } ) ; await testSubjects . existOrFail ( 'transformPivotPreview loaded' , { timeout : 30 * 1000 } ) ; } public async assertTransformsExpandedRowPreviewColumnValues ( column , values ) { await this . waitForTransformsExpandedRowPreviewTabToLoad ( ) ; await this . assertEuiDataGridColumnValues ( 'transformPivotPreview' , column , values ) ; } public async assertTransformDeleteModalExists ( ) { await testSubjects . existOrFail ( 'transformDeleteModal' , { timeout : 60 * 1000 } ) ; } public async assertTransformDeleteModalNotExists ( ) { await testSubjects . missingOrFail ( 'transformDeleteModal' , { timeout : 60 * 1000 } ) ; } public async assertTransformStartModalExists ( ) { await testSubjects . existOrFail ( 'transformStartModal' , { timeout : 60 * 1000 } ) ; } public async assertTransformStartModalNotExists ( ) { await testSubjects . missingOrFail ( 'transformStartModal' , { timeout : 60 * 1000 } ) ; } public async confirmDeleteTransform ( ) { await retry . tryForTime ( 30 * 1000 , async ( ) => { await this . assertTransformDeleteModalExists ( ) ; await testSubjects . click ( 'transformDeleteModal > confirmModalConfirmButton' ) ; await this . assertTransformDeleteModalNotExists ( ) ; } ) ; } public async assertTransformRowNotExists ( transformId ) { await retry . tryForTime ( 30 * 1000 , async ( ) => { const noTransformsFoundMessageExists = await testSubjects . exists ( 'transformNoTransformsFound' ) ; if ( noTransformsFoundMessageExists ) { return true ; } else { await this . filterWithSearchString ( transformId , 0 ) ; } } ) ; } public async confirmStartTransform ( ) { await retry . tryForTime ( 30 * 1000 , async ( ) => { await this . assertTransformStartModalExists ( ) ; await testSubjects . click ( 'transformStartModal > confirmModalConfirmButton' ) ; await this . assertTransformStartModalNotExists ( ) ; } ) ; } } ) ( ) ; }