import expect from '@kbn/expect' ; import { FtrProviderContext } from '../../ftr_provider_context' ; import { MlCommonUI } from './common_ui' ; import { MlCustomUrls } from './custom_urls' ; export interface SectionOptions { withAdvancedSection : boolean ; } export function MachineLearningJobWizardCommonProvider ( { getService } , mlCommonUI , customUrls ) { const comboBox = getService ( 'comboBox' ) ; const retry = getService ( 'retry' ) ; const testSubjects = getService ( 'testSubjects' ) ; function advancedSectionSelector ( subSelector ? ) { const subj = 'mlJobWizardAdvancedSection' ; return ! subSelector ? subj : `${ subj } > ${ subSelector }` ; } return { async clickNextButton ( ) { await testSubjects . existOrFail ( 'mlJobWizardNavButtonNext' ) ; await testSubjects . clickWhenNotDisabled ( 'mlJobWizardNavButtonNext' ) ; } , async assertTimeRangeSectionExists ( ) { await testSubjects . existOrFail ( 'mlJobWizardStepTitleTimeRange' , { timeout : 5000 } ) ; } , async assertPickFieldsSectionExists ( ) { await testSubjects . existOrFail ( 'mlJobWizardStepTitlePickFields' , { timeout : 5000 } ) ; } , async assertJobDetailsSectionExists ( ) { await testSubjects . existOrFail ( 'mlJobWizardStepTitleJobDetails' , { timeout : 5000 } ) ; } , async assertValidationSectionExists ( ) { await testSubjects . existOrFail ( 'mlJobWizardStepTitleValidation' , { timeout : 5000 } ) ; } , async assertSummarySectionExists ( ) { await testSubjects . existOrFail ( 'mlJobWizardStepTitleSummary' , { timeout : 5000 } ) ; } , async assertConfigureDatafeedSectionExists ( ) { await testSubjects . existOrFail ( 'mlJobWizardStepTitleConfigureDatafeed' ) ; } , async advanceToPickFieldsSection ( ) { await retry . tryForTime ( 15 * 1000 , async ( ) => { await this . clickNextButton ( ) ; await this . assertPickFieldsSectionExists ( ) ; } ) ; } , async advanceToJobDetailsSection ( ) { await retry . tryForTime ( 15 * 1000 , async ( ) => { await this . clickNextButton ( ) ; await this . assertJobDetailsSectionExists ( ) ; } ) ; } , async advanceToValidationSection ( ) { await retry . tryForTime ( 15 * 1000 , async ( ) => { await this . clickNextButton ( ) ; await this . assertValidationSectionExists ( ) ; } ) ; } , async advanceToSummarySection ( ) { await retry . tryForTime ( 15 * 1000 , async ( ) => { await this . clickNextButton ( ) ; await this . assertSummarySectionExists ( ) ; } ) ; } , async assertEventRateChartExists ( ) { await testSubjects . existOrFail ( '~mlEventRateChart' ) ; } , async assertEventRateChartHasData ( ) { await testSubjects . existOrFail ( 'mlEventRateChart withData' ) ; } , async assertAggAndFieldInputExists ( ) { await testSubjects . existOrFail ( 'mlJobWizardAggSelection > comboBoxInput' ) ; } , async assertAggAndFieldSelection ( expectedIdentifier ) { const comboBoxSelectedOptions = await comboBox . getComboBoxSelectedOptions ( 'mlJobWizardAggSelection > comboBoxInput' ) ; expect ( comboBoxSelectedOptions ) . to . eql ( expectedIdentifier , `Expected agg and field selection to be '${ expectedIdentifier }' (got '${ comboBoxSelectedOptions }')` ) ; } , async selectAggAndField ( identifier , isIdentifierKeptInField ) { await comboBox . set ( 'mlJobWizardAggSelection > comboBoxInput' , identifier ) ; await this . assertAggAndFieldSelection ( isIdentifierKeptInField ? [ identifier ] : [ ] ) ; } , async assertBucketSpanInputExists ( ) { await testSubjects . existOrFail ( 'mlJobWizardInputBucketSpan' ) ; } , async assertBucketSpanValue ( expectedValue ) { const actualBucketSpan = await testSubjects . getAttribute ( 'mlJobWizardInputBucketSpan' , 'value' ) ; expect ( actualBucketSpan ) . to . eql ( expectedValue , `Expected bucket span value to be '${ expectedValue }' (got '${ actualBucketSpan }')` ) ; } , async setBucketSpan ( bucketSpan ) { await mlCommonUI . setValueWithChecks ( 'mlJobWizardInputBucketSpan' , bucketSpan , { clearWithKeyboard : true , typeCharByChar : true , } ) ; await this . assertBucketSpanValue ( bucketSpan ) ; } , async assertJobIdInputExists ( ) { await testSubjects . existOrFail ( 'mlJobWizardInputJobId' ) ; } , async assertJobIdValue ( expectedValue ) { const actualJobId = await testSubjects . getAttribute ( 'mlJobWizardInputJobId' , 'value' ) ; expect ( actualJobId ) . to . eql ( expectedValue , `Expected job id value to be '${ expectedValue }' (got '${ actualJobId }')` ) ; } , async setJobId ( jobId ) { await mlCommonUI . setValueWithChecks ( 'mlJobWizardInputJobId' , jobId , { clearWithKeyboard : true , } ) ; await this . assertJobIdValue ( jobId ) ; } , async assertJobDescriptionInputExists ( ) { await testSubjects . existOrFail ( 'mlJobWizardInputJobDescription' ) ; } , async assertJobDescriptionValue ( expectedValue ) { const actualJobDescription = await testSubjects . getVisibleText ( 'mlJobWizardInputJobDescription' ) ; expect ( actualJobDescription ) . to . eql ( expectedValue , `Expected job description value to be '${ expectedValue }' (got '${ actualJobDescription }')` ) ; } , async setJobDescription ( jobDescription ) { await mlCommonUI . setValueWithChecks ( 'mlJobWizardInputJobDescription' , jobDescription , { clearWithKeyboard : true , } ) ; await this . assertJobDescriptionValue ( jobDescription ) ; } , async assertJobGroupInputExists ( ) { await testSubjects . existOrFail ( 'mlJobWizardComboBoxJobGroups > comboBoxInput' ) ; } , async getSelectedJobGroups ( ) { return await comboBox . getComboBoxSelectedOptions ( 'mlJobWizardComboBoxJobGroups > comboBoxInput' ) ; } , async assertJobGroupSelection ( jobGroups ) { const actualJobGroupSelection = await this . getSelectedJobGroups ( ) ; expect ( actualJobGroupSelection ) . to . eql ( jobGroups , `Expected job group selection to be '${ jobGroups }' (got '${ actualJobGroupSelection }')` ) ; } , async addJobGroup ( jobGroup ) { await comboBox . setCustom ( 'mlJobWizardComboBoxJobGroups > comboBoxInput' , jobGroup ) ; const actualJobGroupSelection = await this . getSelectedJobGroups ( ) ; expect ( actualJobGroupSelection ) . to . contain ( jobGroup , `Expected job group selection to contain '${ jobGroup }' (got '${ actualJobGroupSelection }')` ) ; } , async getSelectedCalendars ( ) { await this . ensureAdditionalSettingsSectionOpen ( ) ; return await comboBox . getComboBoxSelectedOptions ( 'mlJobWizardComboBoxCalendars > comboBoxInput' ) ; } , async assertCalendarsSelection ( calendars ) { const actualCalendarSelection = await this . getSelectedCalendars ( ) ; expect ( actualCalendarSelection ) . to . eql ( calendars , `Expected calendar selection to be '${ calendars }' (got '${ actualCalendarSelection }')` ) ; } , async addCalendar ( calendarId ) { await this . ensureAdditionalSettingsSectionOpen ( ) ; await comboBox . set ( 'mlJobWizardComboBoxCalendars > comboBoxInput' , calendarId ) ; const actualCalendarSelection = await this . getSelectedCalendars ( ) ; expect ( actualCalendarSelection ) . to . contain ( calendarId , `Expected calendar selection to contain '${ calendarId }' (got '${ actualCalendarSelection }')` ) ; } , async assertModelPlotSwitchExists ( sectionOptions = { withAdvancedSection : true } ) { let subj = 'mlJobWizardSwitchModelPlot' ; if ( sectionOptions . withAdvancedSection === true ) { await this . ensureAdvancedSectionOpen ( ) ; subj = advancedSectionSelector ( subj ) ; } await testSubjects . existOrFail ( subj , { allowHidden : true } ) ; } , async getModelPlotSwitchCheckedState ( sectionOptions = { withAdvancedSection : true } ) { let subj = 'mlJobWizardSwitchModelPlot' ; const isSelected = await testSubjects . getAttribute ( subj , 'aria-checked' ) ; if ( sectionOptions . withAdvancedSection === true ) { await this . ensureAdvancedSectionOpen ( ) ; subj = advancedSectionSelector ( subj ) ; } return isSelected === 'true' ; } , async assertModelPlotSwitchCheckedState ( expectedValue , sectionOptions = { withAdvancedSection : true } ) { const actualCheckedState = await this . getModelPlotSwitchCheckedState ( { withAdvancedSection : sectionOptions . withAdvancedSection , } ) ; expect ( actualCheckedState ) . to . eql ( expectedValue , `Expected model plot switch to be '${ expectedValue ? 'enabled' : 'disabled' }' (got '${ actualCheckedState ? 'enabled' : 'disabled' }')` ) ; } , async assertModelPlotSwitchEnabled ( expectedValue ) { const isEnabled = await testSubjects . isEnabled ( 'mlJobWizardSwitchModelPlot' ) ; expect ( isEnabled ) . to . eql ( expectedValue , `Expected model plot switch to be '${ expectedValue ? 'enabled' : 'disabled' }' (got '${ isEnabled ? 'enabled' : 'disabled' }')` ) ; } , async assertDedicatedIndexSwitchExists ( sectionOptions = { withAdvancedSection : true } ) { let subj = 'mlJobWizardSwitchUseDedicatedIndex' ; if ( sectionOptions . withAdvancedSection === true ) { await this . ensureAdvancedSectionOpen ( ) ; subj = advancedSectionSelector ( subj ) ; } await testSubjects . existOrFail ( subj , { allowHidden : true } ) ; } , async getDedicatedIndexSwitchCheckedState ( sectionOptions = { withAdvancedSection : true } ) { let subj = 'mlJobWizardSwitchUseDedicatedIndex' ; const isSelected = await testSubjects . getAttribute ( subj , 'aria-checked' ) ; if ( sectionOptions . withAdvancedSection === true ) { await this . ensureAdvancedSectionOpen ( ) ; subj = advancedSectionSelector ( subj ) ; } return isSelected === 'true' ; } , async assertDedicatedIndexSwitchCheckedState ( expectedValue , sectionOptions = { withAdvancedSection : true } ) { const actualCheckedState = await this . getDedicatedIndexSwitchCheckedState ( { withAdvancedSection : sectionOptions . withAdvancedSection , } ) ; expect ( actualCheckedState ) . to . eql ( expectedValue , `Expected dedicated index switch to be '${ expectedValue ? 'enabled' : 'disabled' }' (got '${ actualCheckedState ? 'enabled' : 'disabled' }')` ) ; } , async activateDedicatedIndexSwitch ( sectionOptions = { withAdvancedSection : true } ) { let subj = 'mlJobWizardSwitchUseDedicatedIndex' ; if ( sectionOptions . withAdvancedSection === true ) { await this . ensureAdvancedSectionOpen ( ) ; subj = advancedSectionSelector ( subj ) ; } if ( ( await this . getDedicatedIndexSwitchCheckedState ( { withAdvancedSection : sectionOptions . withAdvancedSection , } ) ) === false ) { await retry . tryForTime ( 5 * 1000 , async ( ) => { await testSubjects . clickWhenNotDisabled ( subj ) ; await this . assertDedicatedIndexSwitchCheckedState ( true , { withAdvancedSection : sectionOptions . withAdvancedSection , } ) ; } ) ; } } , async assertStartDatafeedSwitchExists ( ) { const subj = 'mlJobWizardStartDatafeedCheckbox' ; await testSubjects . existOrFail ( subj , { allowHidden : true } ) ; } , async getStartDatafeedSwitchCheckedState ( ) { const subj = 'mlJobWizardStartDatafeedCheckbox' ; const isSelected = await testSubjects . getAttribute ( subj , 'aria-checked' ) ; return isSelected === 'true' ; } , async assertStartDatafeedSwitchCheckedState ( expectedValue ) { const actualCheckedState = await this . getStartDatafeedSwitchCheckedState ( ) ; expect ( actualCheckedState ) . to . eql ( expectedValue , `Expected start datafeed switch to be '${ expectedValue ? 'enabled' : 'disabled' }' (got '${ actualCheckedState ? 'enabled' : 'disabled' }')` ) ; } , async toggleStartDatafeedSwitch ( toggle ) { const subj = 'mlJobWizardStartDatafeedCheckbox' ; if ( ( await this . getStartDatafeedSwitchCheckedState ( ) ) !== toggle ) { await retry . tryForTime ( 5 * 1000 , async ( ) => { await testSubjects . clickWhenNotDisabled ( subj ) ; await this . assertStartDatafeedSwitchCheckedState ( toggle ) ; } ) ; } } , async assertModelMemoryLimitInputExists ( sectionOptions = { withAdvancedSection : true } ) { let subj = 'mlJobWizardInputModelMemoryLimit' ; if ( sectionOptions . withAdvancedSection === true ) { await this . ensureAdvancedSectionOpen ( ) ; subj = advancedSectionSelector ( subj ) ; } await testSubjects . existOrFail ( subj ) ; } , async assertModelMemoryLimitValue ( expectedValue , sectionOptions = { withAdvancedSection : true } ) { let subj = 'mlJobWizardInputModelMemoryLimit' ; if ( sectionOptions . withAdvancedSection === true ) { await this . ensureAdvancedSectionOpen ( ) ; subj = advancedSectionSelector ( subj ) ; } const actualModelMemoryLimit = await testSubjects . getAttribute ( subj , 'value' ) ; expect ( actualModelMemoryLimit ) . to . eql ( expectedValue , `Expected model memory limit value to be '${ expectedValue }' (got '${ actualModelMemoryLimit }')` ) ; } , async setModelMemoryLimit ( modelMemoryLimit , sectionOptions = { withAdvancedSection : true } ) { let subj = 'mlJobWizardInputModelMemoryLimit' ; if ( sectionOptions . withAdvancedSection === true ) { await this . ensureAdvancedSectionOpen ( ) ; subj = advancedSectionSelector ( subj ) ; } await retry . tryForTime ( 15 * 1000 , async ( ) => { await mlCommonUI . setValueWithChecks ( subj , modelMemoryLimit , { clearWithKeyboard : true } ) ; await this . assertModelMemoryLimitValue ( modelMemoryLimit , { withAdvancedSection : sectionOptions . withAdvancedSection , } ) ; } ) ; } , async assertInfluencerInputExists ( ) { await testSubjects . existOrFail ( 'mlInfluencerSelect > comboBoxInput' ) ; } , async getSelectedInfluencers ( ) { return await comboBox . getComboBoxSelectedOptions ( 'mlInfluencerSelect > comboBoxInput' ) ; } , async assertInfluencerSelection ( influencers ) { const actualInfluencerSelection = await this . getSelectedInfluencers ( ) ; expect ( actualInfluencerSelection ) . to . eql ( influencers , `Expected influencer selection to be '${ influencers }' (got '${ actualInfluencerSelection }')` ) ; } , async addInfluencer ( influencer ) { await comboBox . set ( 'mlInfluencerSelect > comboBoxInput' , influencer ) ; const actualInfluencerSelection = await this . getSelectedInfluencers ( ) ; expect ( actualInfluencerSelection ) . to . contain ( influencer , `Expected influencer selection to contain '${ influencer }' (got '${ actualInfluencerSelection }')` ) ; } , async assertAnomalyChartExists ( chartType , preSelector ? ) { let chartSelector = `mlAnomalyChart ${ chartType }` ; chartSelector = ! preSelector ? chartSelector : `${ preSelector } > ${ chartSelector }` ; } , async assertDetectorPreviewExists ( aggAndFieldIdentifier , detectorPosition , chartType ) { await testSubjects . existOrFail ( `mlDetector ${ detectorPosition }` ) ; await testSubjects . existOrFail ( `mlDetector ${ detectorPosition } > mlDetectorTitle` ) ; const actualDetectorTitle = await testSubjects . getVisibleText ( `mlDetector ${ detectorPosition } > mlDetectorTitle` ) ; expect ( actualDetectorTitle ) . to . eql ( aggAndFieldIdentifier , `Expected detector title at position '${ detectorPosition }' to be '${ aggAndFieldIdentifier }' (got '${ actualDetectorTitle }')` ) ; await this . assertAnomalyChartExists ( chartType , `mlDetector ${ detectorPosition }` ) ; } , async assertCreateJobButtonExists ( ) { await testSubjects . existOrFail ( 'mlJobWizardButtonCreateJob' ) ; } , async assertDateRangeSelectionExists ( ) { await testSubjects . existOrFail ( 'mlJobWizardDateRange' ) ; } , async getSelectedDateRange ( ) { const dateRange = await testSubjects . find ( 'mlJobWizardDateRange' ) ; const [ startPicker , endPicker ] = await dateRange . findAllByClassName ( 'euiFieldText' ) ; return { startDate : await startPicker . getAttribute ( 'value' ) , endDate : await endPicker . getAttribute ( 'value' ) , } ; } , async assertDateRangeSelection ( expectedStartDate , expectedEndDate ) { await retry . tryForTime ( 5000 , async ( ) => { const { startDate , endDate } = await this . getSelectedDateRange ( ) ; expect ( startDate ) . to . eql ( expectedStartDate , `Expected start date to be '${ expectedStartDate }' (got '${ startDate }')` ) ; expect ( endDate ) . to . eql ( expectedEndDate , `Expected end date to be '${ expectedEndDate }' (got '${ endDate }')` ) ; } ) ; } , async clickUseFullDataButton ( expectedStartDate , expectedEndDate ) { await testSubjects . clickWhenNotDisabled ( 'mlButtonUseFullData' ) ; await this . assertDateRangeSelection ( expectedStartDate , expectedEndDate ) ; } , async ensureAdditionalSettingsSectionOpen ( ) { await retry . tryForTime ( 5000 , async ( ) => { if ( ( await testSubjects . exists ( 'mlJobWizardAdditionalSettingsSection' ) ) === false ) { await testSubjects . click ( 'mlJobWizardToggleAdditionalSettingsSection' ) ; await testSubjects . existOrFail ( 'mlJobWizardAdditionalSettingsSection' , { timeout : 1000 } ) ; } } ) ; } , async ensureNewCustomUrlFormModalOpen ( ) { await retry . tryForTime ( 5000 , async ( ) => { if ( ( await testSubjects . exists ( 'mlJobNewCustomUrlFormModal' ) ) === false ) { await testSubjects . click ( 'mlJobOpenCustomUrlFormButton' ) ; await testSubjects . existOrFail ( 'mlJobNewCustomUrlFormModal' , { timeout : 1000 } ) ; } } ) ; } , async addCustomUrl ( customUrl ) { await this . ensureAdditionalSettingsSectionOpen ( ) ; const existingCustomUrls = await testSubjects . findAll ( 'mlJobEditCustomUrlsList > *' ) ; await this . ensureNewCustomUrlFormModalOpen ( ) ; await customUrls . setCustomUrlLabel ( customUrl . label ) ; await customUrls . saveCustomUrl ( 'mlJobNewCustomUrlFormModal' ) ; const expectedIndex = existingCustomUrls . length ; await customUrls . assertCustomUrlLabel ( expectedIndex , customUrl . label ) ; } , async ensureAdvancedSectionOpen ( ) { await retry . tryForTime ( 5000 , async ( ) => { if ( ( await testSubjects . exists ( advancedSectionSelector ( ) ) ) === false ) { await testSubjects . click ( 'mlJobWizardToggleAdvancedSection' ) ; await testSubjects . existOrFail ( advancedSectionSelector ( ) , { timeout : 1000 } ) ; } } ) ; } , async createJobAndWaitForCompletion ( ) { await testSubjects . clickWhenNotDisabled ( 'mlJobWizardButtonCreateJob' ) ; await testSubjects . existOrFail ( 'mlJobWizardButtonRunInRealTime' , { timeout : 2 * 60 * 1000 } ) ; } , async createJobWithoutDatafeedStart ( ) { await testSubjects . clickWhenNotDisabled ( 'mlJobWizardButtonCreateJob' ) ; await testSubjects . existOrFail ( 'mlPageJobManagement' ) ; } , } ; }