Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
qn895 committed Oct 3, 2023
1 parent 4c07f9c commit d441274
Show file tree
Hide file tree
Showing 5 changed files with 245 additions and 100 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ export function DataDriftIndexPatternsEditor({
children: (
<EuiFlexItem grow={false}>
<DataViewEditor
key={'reference'}
id={'reference'}
label={
<FormattedMessage
id="xpack.ml.dataDrift.indexPatternsEditor.referenceData"
Expand Down Expand Up @@ -274,7 +274,7 @@ export function DataDriftIndexPatternsEditor({
children: (
<EuiFlexItem grow={false}>
<DataViewEditor
key={'comparison'}
id={'comparison'}
label={
<FormattedMessage
id="xpack.ml.dataDrift.indexPatternsEditor.comparisonDataIndexPatternHelp"
Expand Down Expand Up @@ -389,7 +389,7 @@ export function DataDriftIndexPatternsEditor({
disabled={hasError}
onClick={createDataViewAndRedirectToDataDriftPage.bind(null, true)}
iconType="visTagCloud"
data-test-subj="analyzeDataDriftButton"
data-test-subj="analyzeDataDriftWithoutSavingButton"
aria-label={i18n.translate(
'xpack.ml.dataDrift.indexPatternsEditor.analyzeDataDriftWithoutSavingLabel',
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ import {
import type { DataViewEditorService } from '@kbn/data-view-editor-plugin/public';
import type { MatchedItem } from '@kbn/data-views-plugin/public';
import { useTableSettings } from '../../data_frame_analytics/pages/analytics_management/components/analytics_list/use_table_settings';
import { canAppendWildcard, matchedIndicesDefault } from './data_drift_index_patterns_editor';
import { matchedIndicesDefault } from './data_drift_index_patterns_editor';

interface DataViewEditorProps {
id: string;
label: ReactNode;
dataViewEditorService: DataViewEditorService;
indexPattern: string;
Expand All @@ -42,6 +43,7 @@ const mustMatchError = i18n.translate(
);

export function DataViewEditor({
id,
label,
dataViewEditorService,
indexPattern,
Expand All @@ -65,7 +67,6 @@ export function DataViewEditor({
indexPattern === '' || (indexPattern !== '' && matchedIndices.exactMatchedIndices.length === 0)
? matchedIndices.allIndices
: matchedIndices.exactMatchedIndices;
const [appendedWildcard, setAppendedWildcard] = useState<boolean>(false);

const [pageState, updatePageState] = useState({
pageIndex: 0,
Expand Down Expand Up @@ -131,25 +132,16 @@ export function DataViewEditor({
isInvalid={errorMessage !== undefined}
fullWidth
helpText={helpText}
data-test-subj={`mlDataDriftIndexPatternFormRow-${id ?? ''}`}
>
<EuiFieldText
value={indexPattern}
onChange={(e: ChangeEvent<HTMLInputElement>) => {
let query = e.target.value;
if (query.length === 1 && !appendedWildcard && canAppendWildcard(query)) {
query += '*';
setAppendedWildcard(true);
setTimeout(() => e.target.setSelectionRange(1, 1));
} else {
if (['', '*'].includes(query) && appendedWildcard) {
query = '';
setAppendedWildcard(false);
}
}
const query = e.target.value;
setIndexPattern(query);
}}
fullWidth
data-test-subj="createIndexPatternTitleInput"
data-test-subj={`mlDataDriftIndexPatternTitleInput-${id ?? ''}`}
placeholder="example-pattern*"
/>
</EuiFormRow>
Expand Down Expand Up @@ -183,6 +175,12 @@ export function DataViewEditor({
columns={columns}
pagination={pagination}
onChange={onTableChange}
data-test-subject={`mlDataDriftIndexPatternTable-${id ?? ''}`}
rowProps={(item) => {
return {
'data-test-subj': `mlDataDriftIndexPatternTableRow row-${id}`,
};
}}
/>
</EuiFlexItem>
</EuiFlexGrid>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export const DataDriftIndexOrSearchRedirect: FC = () => {
iconType="plusInCircleFilled"
onClick={() => navigateToPath(createPath(ML_PAGES.DATA_DRIFT_CUSTOM))}
disabled={!canEditDataView}
data-test-subj={'dataDriftCreateDataViewButton'}
>
<FormattedMessage
id="xpack.ml.dataDrift.createDataViewButton"
Expand Down
247 changes: 165 additions & 82 deletions x-pack/test/functional/apps/ml/data_visualizer/data_drift.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,106 +6,189 @@
*/

import { FtrProviderContext } from '../../../ftr_provider_context';
import { farequoteDataViewTestDataWithQuery } from '../../aiops/test_data';
import { TestData } from '../../aiops/types';

export interface TestData {
suiteTitle: string;
dateTimeField: string;
isSavedSearch?: boolean;
sourceIndexOrSavedSearch: string;
chartClickCoordinates: [number, number];
}
export const farequoteKQLFiltersSearchTestData: TestData = {
suiteTitle: 'KQL saved search and filters',
isSavedSearch: true,
dateTimeField: '@timestamp',
sourceIndexOrSavedSearch: 'ft_farequote_filter_and_kuery',
chartClickCoordinates: [0, 0],
};

export default function ({ getService, getPageObjects }: FtrProviderContext) {
const ml = getService('ml');
const PageObjects = getPageObjects(['common', 'console', 'header', 'home', 'security']);
const elasticChart = getService('elasticChart');
const esArchiver = getService('esArchiver');

function runTests(testData: TestData) {
it(`${testData.suiteTitle} loads the source data in data drift`, async () => {
await elasticChart.setNewChartUiDebugFlag(true);
async function assertDataDriftPageContent(testData) {
await ml.testExecution.logTestStep(`${testData.suiteTitle} displays the time range step`);
await ml.dataDrift.assertTimeRangeSelectorSectionExists();

await ml.testExecution.logTestStep(
`${testData.suiteTitle} loads the saved search selection page`
);
await ml.navigation.navigateToDataDrift();
await ml.testExecution.logTestStep(`${testData.suiteTitle} loads data for full time range`);
await ml.dataDrift.clickUseFullDataButton();

await ml.testExecution.logTestStep(
`${testData.suiteTitle} loads the data drift index or saved search select page`
);
await ml.jobSourceSelection.selectSourceForDataDrift(testData.sourceIndexOrSavedSearch);
});
await ml.dataDrift.setRandomSamplingOption('Reference', 'dvRandomSamplerOptionOff');
await ml.dataDrift.setRandomSamplingOption('Comparison', 'dvRandomSamplerOptionOff');

it(`${testData.suiteTitle} displays index details`, async () => {
await ml.testExecution.logTestStep(`${testData.suiteTitle} displays the time range step`);
await ml.dataDrift.assertTimeRangeSelectorSectionExists();
await PageObjects.header.waitUntilLoadingHasFinished();

await ml.testExecution.logTestStep(`${testData.suiteTitle} loads data for full time range`);
await ml.dataDrift.clickUseFullDataButton();
await ml.testExecution.logTestStep(
`${testData.suiteTitle} displays elements in the doc count panel correctly`
);
await ml.dataDrift.assertPrimarySearchBarExists();
await ml.dataDrift.assertReferenceDocCountContent();
await ml.dataDrift.assertComparisonDocCountContent();

await ml.dataDrift.setRandomSamplingOption('Reference', 'dvRandomSamplerOptionOff');
await ml.dataDrift.setRandomSamplingOption('Comparison', 'dvRandomSamplerOptionOff');
await ml.testExecution.logTestStep(
`${testData.suiteTitle} displays elements in the page correctly`
);
await ml.dataDrift.assertNoWindowParametersEmptyPromptExists();

await PageObjects.header.waitUntilLoadingHasFinished();
await ml.testExecution.logTestStep('clicks the document count chart to start analysis');
await ml.dataDrift.clickDocumentCountChart(
'dataDriftDocCountChart-Reference',
testData.chartClickCoordinates
);
await ml.dataDrift.runAnalysis();
}
describe('data drift', async function () {
before(async () => {
await ml.testResources.deleteIndexPatternByTitle('ft_fare*');
await ml.testResources.deleteIndexPatternByTitle('ft_fare*,ft_fareq*');
await ml.testResources.deleteIndexPatternByTitle('ft_ihp_outlier');

await ml.testExecution.logTestStep(
`${testData.suiteTitle} displays elements in the doc count panel correctly`
);
await ml.dataDrift.assertPrimarySearchBarExists();
await ml.dataDrift.assertReferenceDocCountContent();
await ml.dataDrift.assertComparisonDocCountContent();
await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/ihp_outlier');
await ml.testResources.createIndexPatternIfNeeded('ft_ihp_outlier');

await ml.testExecution.logTestStep(
`${testData.suiteTitle} displays elements in the page correctly`
);
await ml.dataDrift.assertNoWindowParametersEmptyPromptExists();
await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/farequote');
await ml.testResources.createIndexPatternIfNeeded('ft_farequote', '@timestamp');
await ml.testResources.createSavedSearchFarequoteFilterAndKueryIfNeeded();

await ml.testExecution.logTestStep('clicks the document count chart to start analysis');
await ml.dataDrift.clickDocumentCountChart(
'dataDriftDocCountChart-Reference',
testData.chartClickCoordinates
);
await ml.dataDrift.runAnalysis();
await ml.testResources.setKibanaTimeZoneToUTC();
await ml.securityUI.loginAsMlPowerUser();
});
after(async () => {
await esArchiver.unload('x-pack/test/functional/es_archives/ml/ihp_outlier');
await esArchiver.unload('x-pack/test/functional/es_archives/ml/farequote');
await ml.testResources.deleteIndexPatternByTitle('ft_fare*');
await ml.testResources.deleteIndexPatternByTitle('ft_fare*,ft_fareq*');
await ml.testResources.deleteIndexPatternByTitle('ft_ihp_outlier');
});
}

describe('data drift', async function () {
for (const testData of [farequoteDataViewTestDataWithQuery]) {
describe(`with '${testData.sourceIndexOrSavedSearch}'`, function () {
before(async () => {
await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/farequote');

await ml.testResources.createIndexPatternIfNeeded(
testData.sourceIndexOrSavedSearch,
'@timestamp'
);

await ml.testResources.setKibanaTimeZoneToUTC();

if (testData.dataGenerator === 'kibana_sample_data_logs') {
await PageObjects.security.login('elastic', 'changeme', {
expectSuccess: true,
});

await PageObjects.common.navigateToUrl('home', '/tutorial_directory/sampleData', {
useActualUrl: true,
});
await PageObjects.header.waitUntilLoadingHasFinished();
await PageObjects.home.addSampleDataSet('logs');
await PageObjects.header.waitUntilLoadingHasFinished();
} else {
await ml.securityUI.loginAsMlPowerUser();
}
});

after(async () => {
await elasticChart.setNewChartUiDebugFlag(false);
await ml.testResources.deleteIndexPatternByTitle(testData.sourceIndexOrSavedSearch);
await esArchiver.unload('x-pack/test/functional/es_archives/ml/farequote');
});

it(`${testData.suiteTitle} loads the ml page`, async () => {
// Start navigation from the base of the ML app.
await ml.navigation.navigateToMl();
await elasticChart.setNewChartUiDebugFlag(true);
});

runTests(testData);
describe('with ft_farequote_filter_and_kuery from index selection page', async function () {
after(async () => {
await elasticChart.setNewChartUiDebugFlag(false);
});

it(`${farequoteKQLFiltersSearchTestData.suiteTitle} loads the ml page`, async () => {
// Start navigation from the base of the ML app.
await ml.navigation.navigateToMl();
await elasticChart.setNewChartUiDebugFlag(true);
});

it(`${farequoteKQLFiltersSearchTestData.suiteTitle} loads the source data in data drift`, async () => {
await ml.testExecution.logTestStep(
`${farequoteKQLFiltersSearchTestData.suiteTitle} loads the data drift index or saved search select page`
);
await ml.navigation.navigateToDataDrift();

await ml.testExecution.logTestStep(
`${farequoteKQLFiltersSearchTestData.suiteTitle} loads the data drift view`
);
await ml.jobSourceSelection.selectSourceForDataDrift(
farequoteKQLFiltersSearchTestData.sourceIndexOrSavedSearch
);
await assertDataDriftPageContent(farequoteKQLFiltersSearchTestData);
});
});

const testData: TestData = {
suiteTitle: 'from data view creation mode',
isSavedSearch: true,
dateTimeField: '@timestamp',
sourceIndexOrSavedSearch: 'ft_farequote_filter_and_kuery',
chartClickCoordinates: [0, 0],
};

describe(testData.suiteTitle, function () {
it(`${testData.suiteTitle} loads the ml page`, async () => {
// Start navigation from the base of the ML app.
await ml.navigation.navigateToMl();
await elasticChart.setNewChartUiDebugFlag(true);
});

it(`${testData.suiteTitle} allows analyzing data drift without setting time field`, async () => {
await ml.testExecution.logTestStep(
`${testData.suiteTitle} loads the saved search selection page`
);
await ml.navigation.navigateToDataDrift();

await ml.testExecution.logTestStep(`${testData.suiteTitle} creates new data view`);
await ml.dataDrift.navigateToCreateNewDataViewPage();
await ml.dataDrift.assertIndexPatternNotEmptyFormErrorExists('reference');
await ml.dataDrift.assertIndexPatternNotEmptyFormErrorExists('comparison');
await ml.dataDrift.assertAnalyzeWithoutSavingButtonState(true);
await ml.dataDrift.assertAnalyzeDataDriftButtonState(true);

await ml.testExecution.logTestStep(`${testData.suiteTitle} sets index patterns`);
await ml.dataDrift.setIndexPatternInput('reference', 'ft_fare*');
await ml.dataDrift.setIndexPatternInput('comparison', 'ft_fareq*');

await ml.dataDrift.assertAnalyzeWithoutSavingButtonState(false);
await ml.dataDrift.assertAnalyzeDataDriftButtonState(false);

await ml.testExecution.logTestStep(`${testData.suiteTitle} redirects to data drift page`);
await ml.dataDrift.clickAnalyzeWithoutSavingButton();
await assertDataDriftPageContent(testData);
});
}

it(`${testData.suiteTitle} hides analyze data drift without saving option if patterns are same`, async () => {
await ml.testExecution.logTestStep(
`${testData.suiteTitle} loads navigates back to data view creation page`
);
await ml.navigation.navigateToDataDrift();
await ml.dataDrift.navigateToCreateNewDataViewPage();
await ml.dataDrift.assertAnalyzeWithoutSavingButtonState(true);
await ml.dataDrift.assertAnalyzeDataDriftButtonState(true);

await ml.testExecution.logTestStep(`${testData.suiteTitle} sets index patterns`);
await ml.dataDrift.setIndexPatternInput('reference', 'ft_fare*');
await ml.dataDrift.setIndexPatternInput('comparison', 'ft_fare*');

await ml.dataDrift.assertAnalyzeWithoutSavingButtonMissing();
await ml.dataDrift.assertAnalyzeDataDriftButtonState(false);

await ml.testExecution.logTestStep(`${testData.suiteTitle} redirects to data drift page`);
await ml.dataDrift.clickAnalyzeDataDrift();
await assertDataDriftPageContent(testData);
});

const nonTimeSeriesTestData: TestData = {
suiteTitle: 'from data view creation mode',
isSavedSearch: false,
dateTimeField: '@timestamp',
sourceIndexOrSavedSearch: 'ft_ihp_outlier',
chartClickCoordinates: [0, 0],
};

it(`${nonTimeSeriesTestData.suiteTitle} loads non-time series data`, async () => {
await ml.testExecution.logTestStep(
`${nonTimeSeriesTestData.suiteTitle} loads navigates back to data view creation page`
);
await ml.navigation.navigateToDataDrift();
await ml.jobSourceSelection.selectSourceForDataDrift(
nonTimeSeriesTestData.sourceIndexOrSavedSearch
);
await ml.dataDrift.runAnalysis();
});
});
});
}
Loading

0 comments on commit d441274

Please sign in to comment.