diff --git a/x-pack/test/api_integration/apis/ml/index.ts b/x-pack/test/api_integration/apis/ml/index.ts index 58356637c63ac5..df99b125e6adb7 100644 --- a/x-pack/test/api_integration/apis/ml/index.ts +++ b/x-pack/test/api_integration/apis/ml/index.ts @@ -37,5 +37,6 @@ export default function({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./fields_service')); loadTestFile(require.resolve('./job_validation')); loadTestFile(require.resolve('./jobs')); + loadTestFile(require.resolve('./results')); }); } diff --git a/x-pack/test/api_integration/apis/ml/results/get_anomalies_table_data.ts b/x-pack/test/api_integration/apis/ml/results/get_anomalies_table_data.ts new file mode 100644 index 00000000000000..9f34a3c639562e --- /dev/null +++ b/x-pack/test/api_integration/apis/ml/results/get_anomalies_table_data.ts @@ -0,0 +1,136 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import expect from '@kbn/expect'; +import { USER } from '../../../../functional/services/machine_learning/security_common'; +import { FtrProviderContext } from '../../../ftr_provider_context'; +import { Datafeed, Job } from '../../../../../plugins/ml/common/types/anomaly_detection_jobs'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext) => { + const esArchiver = getService('esArchiver'); + const supertest = getService('supertestWithoutAuth'); + const ml = getService('ml'); + + const COMMON_HEADERS = { + 'kbn-xsrf': 'some-xsrf-token', + }; + + const JOB_CONFIG: Job = { + job_id: `fq_multi_1_ae`, + description: + 'mean/min/max(responsetime) partition=airline on farequote dataset with 1h bucket span', + groups: ['farequote', 'automated', 'multi-metric'], + analysis_config: { + bucket_span: '1h', + influencers: ['airline'], + detectors: [ + { function: 'mean', field_name: 'responsetime', partition_field_name: 'airline' }, + { function: 'min', field_name: 'responsetime', partition_field_name: 'airline' }, + { function: 'max', field_name: 'responsetime', partition_field_name: 'airline' }, + ], + }, + data_description: { time_field: '@timestamp' }, + analysis_limits: { model_memory_limit: '20mb' }, + model_plot_config: { enabled: true }, + }; + + const DATAFEED_CONFIG: Datafeed = { + datafeed_id: 'datafeed-fq_multi_1_se', + indices: ['ft_farequote'], + job_id: 'fq_multi_1_ae', + query: { bool: { must: [{ match_all: {} }] } }, + }; + + async function createMockJobs() { + await ml.api.createAndRunAnomalyDetectionLookbackJob(JOB_CONFIG, DATAFEED_CONFIG); + } + + describe('GetAnomaliesTableData', () => { + before(async () => { + await esArchiver.loadIfNeeded('ml/farequote'); + await ml.testResources.setKibanaTimeZoneToUTC(); + await createMockJobs(); + }); + + after(async () => { + await ml.api.cleanMlIndices(); + }); + + it('should fetch anomalies table data', async () => { + const requestBody = { + jobIds: [JOB_CONFIG.job_id], + criteriaFields: [{ fieldName: 'detector_index', fieldValue: 0 }], + influencers: [], + aggregationInterval: 'auto', + threshold: 0, + earliestMs: 1454889600000, // February 8, 2016 12:00:00 AM GMT + latestMs: 1454976000000, // February 9, 2016 12:00:00 AM GMT + dateFormatTz: 'UTC', + maxRecords: 500, + }; + + const { body } = await supertest + .post(`/api/ml/results/anomalies_table_data`) + .auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER)) + .set(COMMON_HEADERS) + .send(requestBody) + .expect(200); + + expect(body.interval).to.eql('hour'); + expect(body.anomalies.length).to.eql(12); + }); + + it('should validate request body', async () => { + const requestBody = { + // missing jobIds + criteriaFields: [{ fieldName: 'detector_index', fieldValue: 0 }], + influencers: [], + aggregationInterval: 'auto', + threshold: 0, + // invalid earliest and latest instead of earliestMs and latestMs + earliest: 1454889600000, // February 8, 2016 12:00:00 AM GMT + latest: 1454976000000, // February 9, 2016 12:00:00 AM GMT + dateFormatTz: 'UTC', + maxRecords: 500, + }; + + const { body } = await supertest + .post(`/api/ml/results/anomalies_table_data`) + .auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER)) + .set(COMMON_HEADERS) + .send(requestBody) + .expect(400); + + expect(body.error).to.eql('Bad Request'); + expect(body.message).to.eql( + '[request body.jobIds]: expected value of type [array] but got [undefined]' + ); + }); + + it('should not allow fetching of anomalies table data without required permissions', async () => { + const requestBody = { + jobIds: [JOB_CONFIG.job_id], + criteriaFields: [{ fieldName: 'detector_index', fieldValue: 0 }], + influencers: [], + aggregationInterval: 'auto', + threshold: 0, + earliestMs: 1454889600000, // February 8, 2016 12:00:00 AM GMT + latestMs: 1454976000000, // February 9, 2016 12:00:00 AM GMT + dateFormatTz: 'UTC', + maxRecords: 500, + }; + const { body } = await supertest + .post(`/api/ml/results/anomalies_table_data`) + .auth(USER.ML_UNAUTHORIZED, ml.securityCommon.getPasswordForUser(USER.ML_UNAUTHORIZED)) + .set(COMMON_HEADERS) + .send(requestBody) + .expect(404); + + expect(body.error).to.eql('Not Found'); + expect(body.message).to.eql('Not Found'); + }); + }); +}; diff --git a/x-pack/test/api_integration/apis/ml/results/index.ts b/x-pack/test/api_integration/apis/ml/results/index.ts new file mode 100644 index 00000000000000..80197e6a32ad99 --- /dev/null +++ b/x-pack/test/api_integration/apis/ml/results/index.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function({ loadTestFile }: FtrProviderContext) { + describe('ResultsService', () => { + loadTestFile(require.resolve('./get_anomalies_table_data')); + }); +}