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

[7.x] [ML] Add API integration tests for /filters and /calendars (#72564) #73093

Merged
merged 1 commit into from
Jul 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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