Skip to content

Commit

Permalink
[ML] Add API integration tests for /filters and /calendars (#72564) (#…
Browse files Browse the repository at this point in the history
…73093)

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
  • Loading branch information
qn895 and elasticmachine authored Jul 24, 2020
1 parent a7233f5 commit db3cb40
Show file tree
Hide file tree
Showing 13 changed files with 1,052 additions and 10 deletions.
84 changes: 84 additions & 0 deletions x-pack/test/api_integration/apis/ml/calendars/create_calendars.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* 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 { FtrProviderContext } from '../../../ftr_provider_context';
import { USER } from '../../../../functional/services/ml/security_common';
import { COMMON_REQUEST_HEADERS } from '../../../../functional/services/ml/common';

// eslint-disable-next-line import/no-default-export
export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertestWithoutAuth');
const ml = getService('ml');

describe('create_calendars', function () {
const calendarId = `test_create_calendar`;

const requestBody = {
calendarId,
job_ids: ['test_job_1', 'test_job_2'],
description: 'Test calendar',
events: [
{ description: 'event 1', start_time: 1513641600000, end_time: 1513728000000 },
{ description: 'event 2', start_time: 1513814400000, end_time: 1513900800000 },
{ description: 'event 3', start_time: 1514160000000, end_time: 1514246400000 },
],
};

before(async () => {
await ml.testResources.setKibanaTimeZoneToUTC();
});

afterEach(async () => {
await ml.api.deleteCalendar(calendarId);
});

it('should successfully create calendar by id', async () => {
await supertest
.put(`/api/ml/calendars`)
.auth(USER.ML_POWERUSER, ml.securityCommon.getPasswordForUser(USER.ML_POWERUSER))
.set(COMMON_REQUEST_HEADERS)
.send(requestBody)
.expect(200);

const results = await ml.api.getCalendar(requestBody.calendarId);
const createdCalendar = results.body.calendars[0];

expect(createdCalendar.calendar_id).to.eql(requestBody.calendarId);
expect(createdCalendar.description).to.eql(requestBody.description);
expect(createdCalendar.job_ids).to.eql(requestBody.job_ids);

await ml.api.waitForEventsToExistInCalendar(calendarId, requestBody.events);
});

it('should not create new calendar for user without required permission', async () => {
const { body } = await supertest
.put(`/api/ml/calendars`)
.auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER))
.set(COMMON_REQUEST_HEADERS)
.send(requestBody)
.expect(404);

expect(body.error).to.eql('Not Found');
expect(body.message).to.eql('Not Found');
await ml.api.waitForCalendarNotToExist(calendarId);
});

it('should not create new calendar for unauthorized user', async () => {
const { body } = await supertest
.put(`/api/ml/calendars`)
.auth(USER.ML_UNAUTHORIZED, ml.securityCommon.getPasswordForUser(USER.ML_UNAUTHORIZED))
.set(COMMON_REQUEST_HEADERS)
.send(requestBody)
.expect(404);

expect(body.error).to.eql('Not Found');
expect(body.message).to.eql('Not Found');
await ml.api.waitForCalendarNotToExist(calendarId);
});
});
};
87 changes: 87 additions & 0 deletions x-pack/test/api_integration/apis/ml/calendars/delete_calendars.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* 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 { FtrProviderContext } from '../../../ftr_provider_context';
import { USER } from '../../../../functional/services/ml/security_common';
import { COMMON_REQUEST_HEADERS } from '../../../../functional/services/ml/common';

// eslint-disable-next-line import/no-default-export
export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertestWithoutAuth');
const ml = getService('ml');

describe('delete_calendars', function () {
const calendarId = `test_delete_cal`;
const testCalendar = {
calendar_id: calendarId,
job_ids: ['test_job_1', 'test_job_2'],
description: `Test calendar`,
};
const testEvents = [
{ description: 'event 1', start_time: 1513641600000, end_time: 1513728000000 },
{ description: 'event 2', start_time: 1513814400000, end_time: 1513900800000 },
{ description: 'event 3', start_time: 1514160000000, end_time: 1514246400000 },
];

before(async () => {
await ml.testResources.setKibanaTimeZoneToUTC();
});

beforeEach(async () => {
await ml.api.createCalendar(calendarId, testCalendar);
await ml.api.createCalendarEvents(calendarId, testEvents);
});

afterEach(async () => {
await ml.api.deleteCalendar(calendarId);
});

it('should delete calendar by id', async () => {
const { body } = await supertest
.delete(`/api/ml/calendars/${calendarId}`)
.auth(USER.ML_POWERUSER, ml.securityCommon.getPasswordForUser(USER.ML_POWERUSER))
.set(COMMON_REQUEST_HEADERS)
.expect(200);

expect(body.acknowledged).to.eql(true);
await ml.api.waitForCalendarNotToExist(calendarId);
});

it('should not delete calendar for user without required permission', async () => {
const { body } = await supertest
.delete(`/api/ml/calendars/${calendarId}`)
.auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER))
.set(COMMON_REQUEST_HEADERS)
.expect(404);

expect(body.error).to.eql('Not Found');
await ml.api.waitForCalendarToExist(calendarId);
});

it('should not delete calendar for unauthorized user', async () => {
const { body } = await supertest
.delete(`/api/ml/calendars/${calendarId}`)
.auth(USER.ML_UNAUTHORIZED, ml.securityCommon.getPasswordForUser(USER.ML_UNAUTHORIZED))
.set(COMMON_REQUEST_HEADERS)
.expect(404);

expect(body.error).to.eql('Not Found');
await ml.api.waitForCalendarToExist(calendarId);
});

it('should return 404 if invalid calendarId', async () => {
const { body } = await supertest
.delete(`/api/ml/calendars/calendar_id_dne`)
.auth(USER.ML_POWERUSER, ml.securityCommon.getPasswordForUser(USER.ML_POWERUSER))
.set(COMMON_REQUEST_HEADERS)
.expect(404);

expect(body.error).to.eql('Not Found');
});
});
};
145 changes: 145 additions & 0 deletions x-pack/test/api_integration/apis/ml/calendars/get_calendars.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/*
* 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 { FtrProviderContext } from '../../../ftr_provider_context';
import { USER } from '../../../../functional/services/ml/security_common';
import { COMMON_REQUEST_HEADERS } from '../../../../functional/services/ml/common';

// eslint-disable-next-line import/no-default-export
export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertestWithoutAuth');
const ml = getService('ml');

describe('get_calendars', function () {
const testEvents = [
{ description: 'event 1', start_time: 1513641600000, end_time: 1513728000000 },
{ description: 'event 2', start_time: 1513814400000, end_time: 1513900800000 },
{ description: 'event 3', start_time: 1514160000000, end_time: 1514246400000 },
];

before(async () => {
await ml.testResources.setKibanaTimeZoneToUTC();
});

describe('get multiple calendars', function () {
const testCalendars = [1, 2, 3].map((num) => ({
calendar_id: `test_get_cal_${num}`,
job_ids: ['test_job_1', 'test_job_2'],
description: `Test calendar ${num}`,
}));

beforeEach(async () => {
for (const testCalendar of testCalendars) {
await ml.api.createCalendar(testCalendar.calendar_id, testCalendar);
await ml.api.createCalendarEvents(testCalendar.calendar_id, testEvents);
}
});

afterEach(async () => {
for (const testCalendar of testCalendars) {
await ml.api.deleteCalendar(testCalendar.calendar_id);
}
});

it('should fetch all calendars', async () => {
const { body } = await supertest
.get(`/api/ml/calendars`)
.auth(USER.ML_POWERUSER, ml.securityCommon.getPasswordForUser(USER.ML_POWERUSER))
.set(COMMON_REQUEST_HEADERS)
.expect(200);

expect(body).to.have.length(testCalendars.length);
expect(body[0].events).to.have.length(testEvents.length);
ml.api.assertAllEventsExistInCalendar(testEvents, body[0]);
});

it('should fetch all calendars for user with view permission', async () => {
const { body } = await supertest
.get(`/api/ml/calendars`)
.auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER))
.set(COMMON_REQUEST_HEADERS)
.expect(200);

expect(body).to.have.length(testCalendars.length);
expect(body[0].events).to.have.length(testEvents.length);
ml.api.assertAllEventsExistInCalendar(testEvents, body[0]);
});

it('should not fetch calendars for unauthorized user', async () => {
const { body } = await supertest
.get(`/api/ml/calendars`)
.auth(USER.ML_UNAUTHORIZED, ml.securityCommon.getPasswordForUser(USER.ML_UNAUTHORIZED))
.set(COMMON_REQUEST_HEADERS)
.expect(404);
expect(body.error).to.eql('Not Found');
});
});

describe('get calendar by id', function () {
const calendarId = `test_get_cal`;
const testCalendar = {
calendar_id: calendarId,
job_ids: ['test_job_1', 'test_job_2'],
description: `Test calendar`,
};

beforeEach(async () => {
await ml.api.createCalendar(calendarId, testCalendar);
await ml.api.createCalendarEvents(calendarId, testEvents);
});

afterEach(async () => {
await ml.api.deleteCalendar(calendarId);
});

it('should fetch calendar & associated events by id', async () => {
const { body } = await supertest
.get(`/api/ml/calendars/${calendarId}`)
.auth(USER.ML_POWERUSER, ml.securityCommon.getPasswordForUser(USER.ML_POWERUSER))
.set(COMMON_REQUEST_HEADERS)
.expect(200);

expect(body.job_ids).to.eql(testCalendar.job_ids);
expect(body.description).to.eql(testCalendar.description);
expect(body.events).to.have.length(testEvents.length);
ml.api.assertAllEventsExistInCalendar(testEvents, body);
});

it('should fetch calendar & associated events by id for user with view permission', async () => {
const { body } = await supertest
.get(`/api/ml/calendars/${calendarId}`)
.auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER))
.set(COMMON_REQUEST_HEADERS)
.expect(200);

expect(body.job_ids).to.eql(testCalendar.job_ids);
expect(body.description).to.eql(testCalendar.description);
expect(body.events).to.have.length(testEvents.length);
ml.api.assertAllEventsExistInCalendar(testEvents, body);
});

it('should not fetch calendars for unauthorized user', async () => {
const { body } = await supertest
.get(`/api/ml/calendars/${calendarId}`)
.auth(USER.ML_UNAUTHORIZED, ml.securityCommon.getPasswordForUser(USER.ML_UNAUTHORIZED))
.set(COMMON_REQUEST_HEADERS)
.expect(404);

expect(body.error).to.eql('Not Found');
});
});

it('should return 404 if invalid calendar id', async () => {
const { body } = await supertest
.get(`/api/ml/calendars/calendar_id_dne`)
.auth(USER.ML_POWERUSER, ml.securityCommon.getPasswordForUser(USER.ML_POWERUSER))
.set(COMMON_REQUEST_HEADERS)
.expect(404);
expect(body.error).to.eql('Not Found');
});
});
};
31 changes: 31 additions & 0 deletions x-pack/test/api_integration/apis/ml/calendars/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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 { Calendar, CalendarEvent } from '../../../../../plugins/ml/server/models/calendar';

export const assertAllEventsExistInCalendar = (
eventsToCheck: CalendarEvent[],
calendar: Calendar
): boolean => {
const updatedCalendarEvents = calendar.events as CalendarEvent[];
let allEventsAreUpdated = true;
for (const eventToCheck of eventsToCheck) {
// if at least one of the events that we need to check is not in the updated events
// no need to continue
if (
updatedCalendarEvents.findIndex(
(updatedEvent) =>
updatedEvent.description === eventToCheck.description &&
updatedEvent.start_time === eventToCheck.start_time &&
updatedEvent.end_time === eventToCheck.end_time
) < 0
) {
allEventsAreUpdated = false;
break;
}
}
return allEventsAreUpdated;
};
16 changes: 16 additions & 0 deletions x-pack/test/api_integration/apis/ml/calendars/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* 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('calendars', function () {
loadTestFile(require.resolve('./create_calendars'));
loadTestFile(require.resolve('./get_calendars'));
loadTestFile(require.resolve('./delete_calendars'));
loadTestFile(require.resolve('./update_calendars'));
});
}
Loading

0 comments on commit db3cb40

Please sign in to comment.