From d7b98f5a44bd7e03da552438940f08a37d418af0 Mon Sep 17 00:00:00 2001 From: demjened Date: Wed, 5 Oct 2022 18:01:56 -0400 Subject: [PATCH] Add unit tests --- .../get_inference_errors.test.ts | 77 +++++++++++++++++++ .../routes/enterprise_search/indices.test.ts | 66 ++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 x-pack/plugins/enterprise_search/server/lib/ml_inference_pipeline/get_inference_errors.test.ts diff --git a/x-pack/plugins/enterprise_search/server/lib/ml_inference_pipeline/get_inference_errors.test.ts b/x-pack/plugins/enterprise_search/server/lib/ml_inference_pipeline/get_inference_errors.test.ts new file mode 100644 index 0000000000000..f78dbe5a47eee --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/lib/ml_inference_pipeline/get_inference_errors.test.ts @@ -0,0 +1,77 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ElasticsearchClient } from '@kbn/core/server'; + +import { getMlInferenceErrors } from './get_inference_errors'; + +describe('getMlInferenceErrors', () => { + const indexName = 'my-index'; + + const mockClient = { + search: jest.fn(), + } + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should fetch aggregations and transform them', async () => { + mockClient.search.mockImplementation(() => Promise.resolve({ + aggregations: { + errors: { + buckets: [ + { + key: 'Error message 1', + doc_count: 100, + max_error_timestamp: { + value: 1664977836100, + value_as_string: '2022-10-05T13:50:36.100Z' + } + }, + { + key: 'Error message 2', + doc_count: 200, + max_error_timestamp: { + value: 1664977836200, + value_as_string: '2022-10-05T13:50:36.200Z' + } + }, + ] + } + } + })); + + const actualResult = await getMlInferenceErrors(indexName, mockClient as unknown as ElasticsearchClient); + + expect(actualResult).toEqual([ + { + message: 'Error message 1', + doc_count: 100, + timestamp: '2022-10-05T13:50:36.100Z', + }, + { + message: 'Error message 2', + doc_count: 200, + timestamp: '2022-10-05T13:50:36.200Z', + } + ]); + expect(mockClient.search).toHaveBeenCalledTimes(1); + }); + + it('should return an empty array if there are no aggregates', async () => { + mockClient.search.mockImplementation(() => Promise.resolve({ + aggregations: { + errors: [] + } + })); + + const actualResult = await getMlInferenceErrors(indexName, mockClient as unknown as ElasticsearchClient); + + expect(actualResult).toEqual([]); + }); +}); diff --git a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.test.ts b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.test.ts index 435fb0892019f..e7c2e959ededa 100644 --- a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.test.ts +++ b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.test.ts @@ -23,11 +23,15 @@ jest.mock('../../lib/indices/delete_ml_inference_pipeline', () => ({ jest.mock('../../lib/indices/exists_index', () => ({ indexOrAliasExists: jest.fn(), })); +jest.mock('../../lib/ml_inference_pipeline/get_inference_errors', () => ({ + getMlInferenceErrors: jest.fn(), +})); import { deleteMlInferencePipeline } from '../../lib/indices/delete_ml_inference_pipeline'; import { indexOrAliasExists } from '../../lib/indices/exists_index'; import { fetchMlInferencePipelineProcessors } from '../../lib/indices/fetch_ml_inference_pipeline_processors'; import { createAndReferenceMlInferencePipeline } from '../../utils/create_ml_inference_pipeline'; +import { getMlInferenceErrors } from '../../lib/ml_inference_pipeline/get_inference_errors'; import { ElasticsearchResponseError } from '../../utils/identify_exceptions'; import { registerIndexRoutes } from './indices'; @@ -40,6 +44,7 @@ describe('Enterprise Search Managed Indices', () => { putPipeline: jest.fn(), simulate: jest.fn(), }, + search: jest.fn(), }, }; @@ -47,6 +52,67 @@ describe('Enterprise Search Managed Indices', () => { elasticsearch: { client: mockClient }, }; + describe('GET /internal/enterprise_search/indices/{indexName}/ml_inference/errors', () => { + beforeEach(() => { + const context = { + core: Promise.resolve(mockCore), + } as unknown as jest.Mocked; + + mockRouter = new MockRouter({ + context, + method: 'get', + path: '/internal/enterprise_search/indices/{indexName}/ml_inference/errors', + }); + + registerIndexRoutes({ + ...mockDependencies, + router: mockRouter.router, + }); + }); + + it('fails validation without index_name', () => { + const request = { + params: {}, + }; + mockRouter.shouldThrow(request); + }); + + it('fetches ML inference errors', async () => { + const errorsResult = [ + { + message: 'Error message 1', + doc_count: 100, + timestamp: '2022-10-05T13:50:36.100Z', + }, + { + message: 'Error message 2', + doc_count: 200, + timestamp: '2022-10-05T13:50:36.200Z', + }, + ]; + + (getMlInferenceErrors as jest.Mock).mockImplementationOnce(() => { + return Promise.resolve(errorsResult); + }); + + await mockRouter.callRoute({ + params: { indexName: 'my-index-name' } + }); + + expect(getMlInferenceErrors).toHaveBeenCalledWith( + 'my-index-name', + mockClient.asCurrentUser + ); + + expect(mockRouter.response.ok).toHaveBeenCalledWith({ + body: { + errors: errorsResult, + }, + headers: { 'content-type': 'application/json' }, + }); + }); + }); + describe('GET /internal/enterprise_search/indices/{indexName}/ml_inference/pipeline_processors', () => { beforeEach(() => { const context = {