Skip to content

Commit

Permalink
add more testing, use more function
Browse files Browse the repository at this point in the history
  • Loading branch information
nnamdifrankie committed Jan 6, 2020
1 parent 06ba203 commit 18aaa7b
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 146 deletions.
88 changes: 14 additions & 74 deletions x-pack/plugins/endpoint/server/routes/endpoints.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,13 @@ describe('test endpoint route', () => {
});

it('test find the latest of all endpoints', async () => {
const mockRequest = httpServerMock.createKibanaRequest({
body: {},
params: {},
});
const mockRequest = httpServerMock.createKibanaRequest({});

const response: SearchResponse<EndpointData> = (data as unknown) as SearchResponse<
EndpointData
>;
mockScopedClient.callAsCurrentUser.mockImplementationOnce(() => Promise.resolve(response));
[routeConfig, routeHandler] = routerMock.get.mock.calls.find(([{ path }]) =>
[routeConfig, routeHandler] = routerMock.post.mock.calls.find(([{ path }]) =>
path.startsWith('/api/endpoint/endpoints')
)!;

Expand All @@ -72,38 +69,7 @@ describe('test endpoint route', () => {
mockResponse
);

expect(mockScopedClient.callAsCurrentUser).toBeCalledWith('search', {
from: 0,
size: 10,
body: {
query: {
match_all: {},
},
collapse: {
field: 'machine_id',
inner_hits: {
name: 'most_recent',
size: 1,
sort: [{ created_at: 'desc' }],
},
},
aggs: {
total: {
cardinality: {
field: 'machine_id',
},
},
},
sort: [
{
created_at: {
order: 'desc',
},
},
],
},
index: 'endpoint-agent*',
});
expect(mockScopedClient.callAsCurrentUser).toBeCalled();
expect(routeConfig.options).toEqual({ authRequired: true });
expect(mockResponse.ok).toBeCalled();
const endpointResultList = mockResponse.ok.mock.calls[0][0]?.body as EndpointResultList;
Expand All @@ -115,16 +81,21 @@ describe('test endpoint route', () => {

it('test find the latest of all endpoints with params', async () => {
const mockRequest = httpServerMock.createKibanaRequest({
body: {},
query: {
pageSize: 10,
pageIndex: 1,
body: {
pagingProperties: [
{
pageSize: 10,
},
{
pageIndex: 1,
},
],
},
});
mockScopedClient.callAsCurrentUser.mockImplementationOnce(() =>
Promise.resolve((data as unknown) as SearchResponse<EndpointData>)
);
[routeConfig, routeHandler] = routerMock.get.mock.calls.find(([{ path }]) =>
[routeConfig, routeHandler] = routerMock.post.mock.calls.find(([{ path }]) =>
path.startsWith('/api/endpoint/endpoints')
)!;

Expand All @@ -140,38 +111,7 @@ describe('test endpoint route', () => {
mockResponse
);

expect(mockScopedClient.callAsCurrentUser).toBeCalledWith('search', {
from: 10,
size: 10,
body: {
query: {
match_all: {},
},
collapse: {
field: 'machine_id',
inner_hits: {
name: 'most_recent',
size: 1,
sort: [{ created_at: 'desc' }],
},
},
aggs: {
total: {
cardinality: {
field: 'machine_id',
},
},
},
sort: [
{
created_at: {
order: 'desc',
},
},
],
},
index: 'endpoint-agent*',
});
expect(mockScopedClient.callAsCurrentUser).toBeCalled();
expect(routeConfig.options).toEqual({ authRequired: true });
expect(mockResponse.ok).toBeCalled();
const endpointResultList = mockResponse.ok.mock.calls[0][0]?.body as EndpointResultList;
Expand Down
36 changes: 22 additions & 14 deletions x-pack/plugins/endpoint/server/routes/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { IRouter } from 'kibana/server';
import { SearchResponse } from 'elasticsearch';
import { schema } from '@kbn/config-schema';
import { EndpointAppContext, EndpointData } from '../types';
import { AllEndpointsQueryBuilder } from '../services/endpoint/endpoint_query_builders';
import { kibanaRequestToEndpointListQuery } from '../services/endpoint/endpoint_query_builders';
import { RouteSchemas } from '../../../../../build/kibana/src/core/server/http/router/route';

interface HitSource {
_source: EndpointData;
Expand All @@ -25,26 +26,33 @@ export interface EndpointResultList {
requestIndex: number;
}

const endpointListRequestSchema: RouteSchemas<any, any, any> = {
body: schema.nullable(
schema.object({
pagingProperties: schema.arrayOf(
schema.oneOf([
// the number of results to return for this request per page
schema.object({
pageSize: schema.number({ defaultValue: 10, min: 1, max: 10000 }),
}),
// the index of the page to return
schema.object({ pageIndex: schema.number({ defaultValue: 0, min: 0 }) }),
])
),
})
),
};

export function registerEndpointRoutes(router: IRouter, endpointAppContext: EndpointAppContext) {
router.get(
router.post(
{
path: '/api/endpoint/endpoints',
validate: {
query: schema.object({
// the number of results to return for this request per page
pageSize: schema.number({ defaultValue: 10, min: 1 }),
// the index of the page to return
pageIndex: schema.number({ defaultValue: 0, min: 0 }),
}),
},
validate: endpointListRequestSchema,
options: { authRequired: true },
},
async (context, req, res) => {
try {
const queryParams = await new AllEndpointsQueryBuilder(
req,
endpointAppContext
).toQueryParams();
const queryParams = await kibanaRequestToEndpointListQuery(req, endpointAppContext);
const response = (await context.core.elasticsearch.dataClient.callAsCurrentUser(
'search',
queryParams
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,18 @@
*/
import { httpServerMock, loggingServiceMock } from '../../../../../../src/core/server/mocks';
import { EndpointConfigSchema } from '../../config';
import { AllEndpointsQueryBuilder } from './endpoint_query_builders';
import { kibanaRequestToEndpointListQuery } from './endpoint_query_builders';

describe('test query builder', () => {
describe('test query builder request processing', () => {
it('test default query params for all endpoints when no params or body is provided', async () => {
const mockRequest = httpServerMock.createKibanaRequest({
body: {},
});
const searchQueryBuilder = new AllEndpointsQueryBuilder(mockRequest, {
const query = await kibanaRequestToEndpointListQuery(mockRequest, {
logFactory: loggingServiceMock.create(),
config: () => Promise.resolve(EndpointConfigSchema.validate({})),
});
const query = await searchQueryBuilder.toQueryParams();
expect(query).toEqual({
body: {
query: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,62 +6,61 @@
import { KibanaRequest } from 'kibana/server';
import { EndpointAppConstants, EndpointAppContext } from '../../types';

export class AllEndpointsQueryBuilder {
private readonly request: KibanaRequest<any, any, any>;
private readonly endpointAppContext: EndpointAppContext;

constructor(request: KibanaRequest<any, any, any>, endpointAppContext: EndpointAppContext) {
this.request = request;
this.endpointAppContext = endpointAppContext;
}
/* aggregating by endpoint machine id and retrieving the latest of each group of events
related to an endpoint by machine id using elastic search collapse functionality
*/
async toQueryParams(): Promise<Record<string, any>> {
const paging = await this.paging();
return {
body: {
query: this.queryBody(),
collapse: {
field: 'machine_id',
inner_hits: {
name: 'most_recent',
size: 1,
sort: [{ created_at: 'desc' }],
},
export const kibanaRequestToEndpointListQuery = async (
request: KibanaRequest<any, any, any>,
endpointAppContext: EndpointAppContext
): Promise<Record<string, any>> => {
const pagingProperties = await getPagingProperties(request, endpointAppContext);
return {
body: {
query: {
match_all: {},
},
collapse: {
field: 'machine_id',
inner_hits: {
name: 'most_recent',
size: 1,
sort: [{ created_at: 'desc' }],
},
aggs: {
total: {
cardinality: {
field: 'machine_id',
},
},
aggs: {
total: {
cardinality: {
field: 'machine_id',
},
},
sort: [
{
created_at: {
order: 'desc',
},
},
],
},
from: paging.pageIndex * paging.pageSize,
size: paging.pageSize,
index: EndpointAppConstants.ENDPOINT_INDEX_NAME,
};
}

private queryBody(): Record<string, unknown> {
return {
match_all: {},
};
}
sort: [
{
created_at: {
order: 'desc',
},
},
],
},
from: pagingProperties.pageIndex * pagingProperties.pageSize,
size: pagingProperties.pageSize,
index: EndpointAppConstants.ENDPOINT_INDEX_NAME,
};
};

private async paging() {
const config = await this.endpointAppContext.config();
return {
pageSize: this.request.query.pageSize || config.endpointResultListDefaultPageSize,
pageIndex: this.request.query.pageIndex || config.endpointResultListDefaultFirstPageIndex,
};
async function getPagingProperties(
request: KibanaRequest<any, any, any>,
endpointAppContext: EndpointAppContext
) {
const config = await endpointAppContext.config();
const pagingProperties: { pageSize?: number; pageIndex?: number } = {};
if (request?.body?.pagingProperties) {
for (const property of request.body.pagingProperties) {
Object.assign(
pagingProperties,
...Object.keys(property).map(key => ({ [key]: property[key] }))
);
}
}
return {
pageSize: pagingProperties.pageSize || config.endpointResultListDefaultPageSize,
pageIndex: pagingProperties.pageIndex || config.endpointResultListDefaultFirstPageIndex,
};
}
33 changes: 30 additions & 3 deletions x-pack/test/api_integration/apis/endpoint/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default function({ getService }: FtrProviderContext) {
describe('GET /api/endpoint/endpoints', () => {
it('endpoints api should return one entry for each endpoint with default paging', async () => {
const { body } = await supertest
.get('/api/endpoint/endpoints')
.post('/api/endpoint/endpoints')
.set('kbn-xsrf', 'xxx')
.send()
.expect(200);
Expand All @@ -27,15 +27,42 @@ export default function({ getService }: FtrProviderContext) {

it('endpoints api should return page based on params passed.', async () => {
const { body } = await supertest
.get('/api/endpoint/endpoints?pageSize=1&pageIndex=1')
.post('/api/endpoint/endpoints')
.set('kbn-xsrf', 'xxx')
.send()
.send({
pagingProperties: [
{
pageSize: 1,
},
{
pageIndex: 1,
},
],
})
.expect(200);
expect(body.total).to.eql(3);
expect(body.endpoints.length).to.eql(1);
expect(body.requestPageSize).to.eql(1);
expect(body.requestIndex).to.eql(1);
});

it('endpoints api should return 400 when pagingProperties is below boundaries.', async () => {
const { body } = await supertest
.post('/api/endpoint/endpoints')
.set('kbn-xsrf', 'xxx')
.send({
pagingProperties: [
{
pageSize: 0,
},
{
pageIndex: 1,
},
],
})
.expect(400);
expect(body.message).to.contain('Value is [0] but it must be equal to or greater than [1]');
});
});
});
}

0 comments on commit 18aaa7b

Please sign in to comment.