mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
Bind create engine button to the backend (#128253)
This commit is contained in:
parent
03ce76bb70
commit
4cd7f879a8
5 changed files with 260 additions and 110 deletions
|
@ -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
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { SearchIndexSelectableOption } from '../components/engine_creation/search_index_selectable';
|
||||
|
||||
export const DEFAULT_VALUES = {
|
||||
ingestionMethod: '',
|
||||
isLoading: false,
|
||||
name: '',
|
||||
rawName: '',
|
||||
language: 'Universal',
|
||||
isLoadingIndices: false,
|
||||
indices: [],
|
||||
indicesFormatted: [],
|
||||
selectedIndex: '',
|
||||
engineType: 'appSearch',
|
||||
isSubmitDisabled: true,
|
||||
};
|
||||
|
||||
export const mockElasticsearchIndices = [
|
||||
{
|
||||
health: 'yellow',
|
||||
status: 'open',
|
||||
name: 'search-my-index-1',
|
||||
uuid: 'ydlR_QQJTeyZP66tzQSmMQ',
|
||||
total: {
|
||||
docs: {
|
||||
count: 0,
|
||||
deleted: 0,
|
||||
},
|
||||
store: {
|
||||
size_in_bytes: '225b',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
health: 'green',
|
||||
status: 'open',
|
||||
name: 'search-my-index-2',
|
||||
uuid: '4dlR_QQJTe2ZP6qtzQSmMQ',
|
||||
total: {
|
||||
docs: {
|
||||
count: 100,
|
||||
deleted: 0,
|
||||
},
|
||||
store: {
|
||||
size_in_bytes: '225b',
|
||||
},
|
||||
},
|
||||
aliases: ['search-index-123'],
|
||||
},
|
||||
];
|
||||
|
||||
export const mockSearchIndexOptions: SearchIndexSelectableOption[] = [
|
||||
{
|
||||
label: 'search-my-index-1',
|
||||
health: 'yellow',
|
||||
status: 'open',
|
||||
total: {
|
||||
docs: {
|
||||
count: 0,
|
||||
deleted: 0,
|
||||
},
|
||||
store: {
|
||||
size_in_bytes: '225b',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'search-my-index-2',
|
||||
health: 'green',
|
||||
status: 'open',
|
||||
total: {
|
||||
docs: {
|
||||
count: 100,
|
||||
deleted: 0,
|
||||
},
|
||||
store: {
|
||||
size_in_bytes: '225b',
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
|
@ -12,10 +12,15 @@ import {
|
|||
mockFlashMessageHelpers,
|
||||
} from '../../../__mocks__/kea_logic';
|
||||
|
||||
import {
|
||||
DEFAULT_VALUES,
|
||||
mockElasticsearchIndices,
|
||||
mockSearchIndexOptions,
|
||||
} from '../../__mocks__/engine_creation_logic.mock';
|
||||
|
||||
import { nextTick } from '@kbn/test-jest-helpers';
|
||||
|
||||
import { EngineCreationLogic } from './engine_creation_logic';
|
||||
import { SearchIndexSelectableOption } from './search_index_selectable';
|
||||
|
||||
describe('EngineCreationLogic', () => {
|
||||
const { mount } = new LogicMounter(EngineCreationLogic);
|
||||
|
@ -23,85 +28,6 @@ describe('EngineCreationLogic', () => {
|
|||
const { navigateToUrl } = mockKibanaValues;
|
||||
const { flashSuccessToast, flashAPIErrors } = mockFlashMessageHelpers;
|
||||
|
||||
const DEFAULT_VALUES = {
|
||||
ingestionMethod: '',
|
||||
isLoading: false,
|
||||
name: '',
|
||||
rawName: '',
|
||||
language: 'Universal',
|
||||
isLoadingIndices: false,
|
||||
indices: [],
|
||||
indicesFormatted: [],
|
||||
selectedIndex: '',
|
||||
engineType: 'appSearch',
|
||||
isSubmitDisabled: true,
|
||||
};
|
||||
|
||||
const mockElasticsearchIndices = [
|
||||
{
|
||||
health: 'yellow',
|
||||
status: 'open',
|
||||
name: 'search-my-index-1',
|
||||
uuid: 'ydlR_QQJTeyZP66tzQSmMQ',
|
||||
total: {
|
||||
docs: {
|
||||
count: 0,
|
||||
deleted: 0,
|
||||
},
|
||||
store: {
|
||||
size_in_bytes: '225b',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
health: 'green',
|
||||
status: 'open',
|
||||
name: 'search-my-index-2',
|
||||
uuid: '4dlR_QQJTe2ZP6qtzQSmMQ',
|
||||
total: {
|
||||
docs: {
|
||||
count: 100,
|
||||
deleted: 0,
|
||||
},
|
||||
store: {
|
||||
size_in_bytes: '225b',
|
||||
},
|
||||
},
|
||||
aliases: ['search-index-123'],
|
||||
},
|
||||
];
|
||||
|
||||
const mockSearchIndexOptions: SearchIndexSelectableOption[] = [
|
||||
{
|
||||
label: 'search-my-index-1',
|
||||
health: 'yellow',
|
||||
status: 'open',
|
||||
total: {
|
||||
docs: {
|
||||
count: 0,
|
||||
deleted: 0,
|
||||
},
|
||||
store: {
|
||||
size_in_bytes: '225b',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'search-my-index-2',
|
||||
health: 'green',
|
||||
status: 'open',
|
||||
total: {
|
||||
docs: {
|
||||
count: 100,
|
||||
deleted: 0,
|
||||
},
|
||||
store: {
|
||||
size_in_bytes: '225b',
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
it('has expected default values', () => {
|
||||
mount();
|
||||
expect(EngineCreationLogic.values).toEqual(DEFAULT_VALUES);
|
||||
|
@ -333,36 +259,82 @@ describe('EngineCreationLogic', () => {
|
|||
});
|
||||
|
||||
describe('submitEngine', () => {
|
||||
beforeAll(() => {
|
||||
mount({ language: 'English', rawName: 'test' });
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('POSTS to /internal/app_search/engines', () => {
|
||||
const body = JSON.stringify({
|
||||
name: EngineCreationLogic.values.name,
|
||||
language: EngineCreationLogic.values.language,
|
||||
describe('Indexed engine', () => {
|
||||
beforeAll(() => {
|
||||
mount({ language: 'English', rawName: 'test' });
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('POSTS to /internal/app_search/engines', () => {
|
||||
const body = JSON.stringify({
|
||||
name: EngineCreationLogic.values.name,
|
||||
language: EngineCreationLogic.values.language,
|
||||
});
|
||||
EngineCreationLogic.actions.submitEngine();
|
||||
expect(http.post).toHaveBeenCalledWith('/internal/app_search/engines', { body });
|
||||
});
|
||||
|
||||
it('calls onEngineCreationSuccess on valid submission', async () => {
|
||||
jest.spyOn(EngineCreationLogic.actions, 'onEngineCreationSuccess');
|
||||
http.post.mockReturnValueOnce(Promise.resolve({}));
|
||||
EngineCreationLogic.actions.submitEngine();
|
||||
await nextTick();
|
||||
expect(EngineCreationLogic.actions.onEngineCreationSuccess).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('calls flashAPIErrors on API Error', async () => {
|
||||
http.post.mockReturnValueOnce(Promise.reject());
|
||||
EngineCreationLogic.actions.submitEngine();
|
||||
await nextTick();
|
||||
expect(flashAPIErrors).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
EngineCreationLogic.actions.submitEngine();
|
||||
expect(http.post).toHaveBeenCalledWith('/internal/app_search/engines', { body });
|
||||
});
|
||||
|
||||
it('calls onEngineCreationSuccess on valid submission', async () => {
|
||||
jest.spyOn(EngineCreationLogic.actions, 'onEngineCreationSuccess');
|
||||
http.post.mockReturnValueOnce(Promise.resolve({}));
|
||||
EngineCreationLogic.actions.submitEngine();
|
||||
await nextTick();
|
||||
expect(EngineCreationLogic.actions.onEngineCreationSuccess).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
describe('Elasticsearch index based engine', () => {
|
||||
beforeEach(() => {
|
||||
mount({
|
||||
engineType: 'elasticsearch',
|
||||
name: 'engine-name',
|
||||
selectedIndex: 'search-selected-index',
|
||||
});
|
||||
});
|
||||
|
||||
it('calls flashAPIErrors on API Error', async () => {
|
||||
http.post.mockReturnValueOnce(Promise.reject());
|
||||
EngineCreationLogic.actions.submitEngine();
|
||||
await nextTick();
|
||||
expect(flashAPIErrors).toHaveBeenCalledTimes(1);
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('POSTS to /internal/app_search/elasticsearch/engines', () => {
|
||||
const body = JSON.stringify({
|
||||
name: EngineCreationLogic.values.name,
|
||||
search_index: {
|
||||
type: 'elasticsearch',
|
||||
index_name: EngineCreationLogic.values.selectedIndex,
|
||||
},
|
||||
});
|
||||
EngineCreationLogic.actions.submitEngine();
|
||||
|
||||
expect(http.post).toHaveBeenCalledWith('/internal/app_search/elasticsearch/engines', {
|
||||
body,
|
||||
});
|
||||
});
|
||||
|
||||
it('calls onEngineCreationSuccess on valid submission', async () => {
|
||||
jest.spyOn(EngineCreationLogic.actions, 'onEngineCreationSuccess');
|
||||
http.post.mockReturnValueOnce(Promise.resolve({}));
|
||||
EngineCreationLogic.actions.submitEngine();
|
||||
await nextTick();
|
||||
expect(EngineCreationLogic.actions.onEngineCreationSuccess).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('calls flashAPIErrors on API Error', async () => {
|
||||
http.post.mockReturnValueOnce(Promise.reject());
|
||||
EngineCreationLogic.actions.submitEngine();
|
||||
await nextTick();
|
||||
expect(flashAPIErrors).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -130,12 +130,23 @@ export const EngineCreationLogic = kea<MakeLogicType<EngineCreationValues, Engin
|
|||
listeners: ({ values, actions }) => ({
|
||||
submitEngine: async () => {
|
||||
const { http } = HttpLogic.values;
|
||||
const { name, language } = values;
|
||||
|
||||
const body = JSON.stringify({ name, language });
|
||||
const { name, language, engineType, selectedIndex } = values;
|
||||
|
||||
try {
|
||||
await http.post('/internal/app_search/engines', { body });
|
||||
if (engineType === 'appSearch') {
|
||||
const body = JSON.stringify({ name, language });
|
||||
|
||||
await http.post('/internal/app_search/engines', { body });
|
||||
} else {
|
||||
const body = JSON.stringify({
|
||||
name,
|
||||
search_index: {
|
||||
type: 'elasticsearch',
|
||||
index_name: selectedIndex,
|
||||
},
|
||||
});
|
||||
await http.post('/internal/app_search/elasticsearch/engines', { body });
|
||||
}
|
||||
actions.onEngineCreationSuccess();
|
||||
} catch (e) {
|
||||
flashAPIErrors(e);
|
||||
|
|
|
@ -176,6 +176,68 @@ describe('engine routes', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('POST /internal/app_search/elasticsearch/engines', () => {
|
||||
let mockRouter: MockRouter;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
mockRouter = new MockRouter({
|
||||
method: 'post',
|
||||
path: '/internal/app_search/elasticsearch/engines',
|
||||
});
|
||||
|
||||
registerEnginesRoutes({
|
||||
...mockDependencies,
|
||||
router: mockRouter.router,
|
||||
});
|
||||
});
|
||||
|
||||
it('creates a request handler', () => {
|
||||
mockRouter.callRoute({
|
||||
body: {
|
||||
name: 'some-elasticindexed-engine',
|
||||
search_index: { type: 'elasticsearch', index_name: 'search-elastic-index' },
|
||||
},
|
||||
});
|
||||
expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({
|
||||
path: '/api/as/v0/engines',
|
||||
});
|
||||
});
|
||||
|
||||
describe('validates', () => {
|
||||
describe('indexed engines', () => {
|
||||
it('correctly', () => {
|
||||
const request = {
|
||||
body: {
|
||||
name: 'some-engine',
|
||||
search_index: { type: 'elasticsearch', index_name: 'search-elastic-index' },
|
||||
},
|
||||
};
|
||||
mockRouter.shouldValidate(request);
|
||||
});
|
||||
|
||||
it('missing name', () => {
|
||||
const request = {
|
||||
body: {
|
||||
search_index: { type: 'elasticsearch', index_name: 'search-elastic-index' },
|
||||
},
|
||||
};
|
||||
mockRouter.shouldThrow(request);
|
||||
});
|
||||
|
||||
it('missing index_name', () => {
|
||||
const request = {
|
||||
name: 'some-engine',
|
||||
body: {
|
||||
search_index: { type: 'elasticsearch' },
|
||||
},
|
||||
};
|
||||
mockRouter.shouldThrow(request);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /internal/app_search/engines/{name}', () => {
|
||||
let mockRouter: MockRouter;
|
||||
|
||||
|
|
|
@ -55,6 +55,24 @@ export function registerEnginesRoutes({
|
|||
})
|
||||
);
|
||||
|
||||
router.post(
|
||||
{
|
||||
path: '/internal/app_search/elasticsearch/engines',
|
||||
validate: {
|
||||
body: schema.object({
|
||||
name: schema.string(),
|
||||
search_index: schema.object({
|
||||
type: schema.string(),
|
||||
index_name: schema.string(),
|
||||
}),
|
||||
}),
|
||||
},
|
||||
},
|
||||
enterpriseSearchRequestHandler.createRequest({
|
||||
path: '/api/as/v0/engines',
|
||||
})
|
||||
);
|
||||
|
||||
// Single engine endpoints
|
||||
router.get(
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue