Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ML] Add API integration tests for /filters and /calendars #72564

Merged
merged 8 commits into from
Jul 23, 2020
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);
pheyos marked this conversation as resolved.
Show resolved Hide resolved

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');
});
});
};
146 changes: 146 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,146 @@
/*
* 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 { allEventsExistInCalendar } from './helpers';
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);
expect(allEventsExistInCalendar(testEvents, body[0])).to.eql(true);
});

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);
expect(allEventsExistInCalendar(testEvents, body[0])).to.eql(true);
});

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 () {
pheyos marked this conversation as resolved.
Show resolved Hide resolved
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);
expect(allEventsExistInCalendar(testEvents, body)).to.eql(true);
});

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);
expect(allEventsExistInCalendar(testEvents, body)).to.eql(true);
});

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 allEventsExistInCalendar = (
pheyos marked this conversation as resolved.
Show resolved Hide resolved
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
pheyos marked this conversation as resolved.
Show resolved Hide resolved
) {
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