Skip to content

Commit

Permalink
Merge branch 'master' into reporting/browser-install-cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
tsullivan committed Apr 30, 2021
2 parents ef22598 + 7cabbb8 commit ca531a9
Show file tree
Hide file tree
Showing 26 changed files with 500 additions and 119 deletions.
2 changes: 1 addition & 1 deletion Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ kibanaLibrary.load()
kibanaPipeline(timeoutMinutes: 210, checkPrChanges: true, setCommitStatus: true) {
slackNotifications.onFailure(disabled: !params.NOTIFY_ON_FAILURE) {
githubPr.withDefaultPrComments {
ciStats.trackBuild {
ciStats.trackBuild(requireSuccess: githubPr.isPr()) {
catchError {
retryable.enable()
kibanaPipeline.allCiTasks()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@

export { SEARCH_UI_TITLE } from './constants';
export { SearchUI } from './search_ui';
export { SearchUILogic } from './search_ui_logic';
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,34 @@
* 2.0.
*/

import '../../../__mocks__/shallow_useeffect.mock';
import '../../__mocks__/engine_logic.mock';

import { setMockActions } from '../../../__mocks__';

import React from 'react';

import { shallow } from 'enzyme';

import { SearchUI } from './';

describe('SearchUI', () => {
const actions = {
loadFieldData: jest.fn(),
};

beforeEach(() => {
jest.clearAllMocks();
setMockActions(actions);
});

it('renders', () => {
shallow(<SearchUI />);
// TODO: Check for form
});

it('initializes data on mount', () => {
shallow(<SearchUI />);
expect(actions.loadFieldData).toHaveBeenCalledTimes(1);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
* 2.0.
*/

import React from 'react';
import React, { useEffect } from 'react';

import { useActions } from 'kea';

import { EuiPageHeader, EuiPageContentBody } from '@elastic/eui';

Expand All @@ -15,8 +17,15 @@ import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chro
import { getEngineBreadcrumbs } from '../engine';

import { SEARCH_UI_TITLE } from './constants';
import { SearchUILogic } from './search_ui_logic';

export const SearchUI: React.FC = () => {
const { loadFieldData } = useActions(SearchUILogic);

useEffect(() => {
loadFieldData();
}, []);

return (
<>
<SetPageChrome trail={getEngineBreadcrumbs([SEARCH_UI_TITLE])} />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/*
* 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 { LogicMounter, mockFlashMessageHelpers, mockHttpValues } from '../../../__mocks__';

import { mockEngineValues } from '../../__mocks__';

import { nextTick } from '@kbn/test/jest';

import { ActiveField } from './types';

import { SearchUILogic } from './';

describe('SearchUILogic', () => {
const { mount } = new LogicMounter(SearchUILogic);
const { http } = mockHttpValues;
const { flashAPIErrors } = mockFlashMessageHelpers;

const DEFAULT_VALUES = {
dataLoading: true,
validFields: [],
validSortFields: [],
validFacetFields: [],
titleField: '',
urlField: '',
facetFields: [],
sortFields: [],
activeField: ActiveField.None,
};

beforeEach(() => {
jest.clearAllMocks();
mockEngineValues.engineName = 'engine1';
});

it('has expected default values', () => {
mount();
expect(SearchUILogic.values).toEqual(DEFAULT_VALUES);
});

describe('actions', () => {
describe('onFieldDataLoaded', () => {
it('sets initial field values fetched from API call and sets dataLoading to false', () => {
mount({
validFields: [],
validSortFields: [],
validFacetFields: [],
});

SearchUILogic.actions.onFieldDataLoaded({
validFields: ['foo'],
validSortFields: ['bar'],
validFacetFields: ['baz'],
});

expect(SearchUILogic.values).toEqual({
...DEFAULT_VALUES,
dataLoading: false,
validFields: ['foo'],
validSortFields: ['bar'],
validFacetFields: ['baz'],
});
});
});

describe('onTitleFieldChange', () => {
it('sets the titleField value', () => {
mount({ titleField: '' });
SearchUILogic.actions.onTitleFieldChange('foo');
expect(SearchUILogic.values).toEqual({
...DEFAULT_VALUES,
titleField: 'foo',
});
});
});

describe('onURLFieldChange', () => {
it('sets the urlField value', () => {
mount({ urlField: '' });
SearchUILogic.actions.onURLFieldChange('foo');
expect(SearchUILogic.values).toEqual({
...DEFAULT_VALUES,
urlField: 'foo',
});
});
});

describe('onFacetFieldsChange', () => {
it('sets the facetFields value', () => {
mount({ facetFields: [] });
SearchUILogic.actions.onFacetFieldsChange(['foo']);
expect(SearchUILogic.values).toEqual({
...DEFAULT_VALUES,
facetFields: ['foo'],
});
});
});

describe('onSortFieldsChange', () => {
it('sets the sortFields value', () => {
mount({ sortFields: [] });
SearchUILogic.actions.onSortFieldsChange(['foo']);
expect(SearchUILogic.values).toEqual({
...DEFAULT_VALUES,
sortFields: ['foo'],
});
});
});

describe('onActiveFieldChange', () => {
it('sets the activeField value', () => {
mount({ activeField: '' });
SearchUILogic.actions.onActiveFieldChange(ActiveField.Sort);
expect(SearchUILogic.values).toEqual({
...DEFAULT_VALUES,
activeField: ActiveField.Sort,
});
});
});
});

describe('listeners', () => {
const MOCK_RESPONSE = {
validFields: ['test'],
validSortFields: ['test'],
validFacetFields: ['test'],
};

describe('loadFieldData', () => {
it('should make an API call and set state based on the response', async () => {
http.get.mockReturnValueOnce(Promise.resolve(MOCK_RESPONSE));
mount();
jest.spyOn(SearchUILogic.actions, 'onFieldDataLoaded');

SearchUILogic.actions.loadFieldData();
await nextTick();

expect(http.get).toHaveBeenCalledWith(
'/api/app_search/engines/engine1/search_ui/field_config'
);
expect(SearchUILogic.actions.onFieldDataLoaded).toHaveBeenCalledWith(MOCK_RESPONSE);
});

it('handles errors', async () => {
http.get.mockReturnValueOnce(Promise.reject('error'));
mount();

SearchUILogic.actions.loadFieldData();
await nextTick();

expect(flashAPIErrors).toHaveBeenCalledWith('error');
});
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* 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 { kea, MakeLogicType } from 'kea';

import { flashAPIErrors } from '../../../shared/flash_messages';
import { HttpLogic } from '../../../shared/http';
import { EngineLogic } from '../engine';

import { ActiveField } from './types';

interface InitialFieldValues {
validFields: string[];
validSortFields: string[];
validFacetFields: string[];
}
interface SearchUIActions {
loadFieldData(): void;
onFieldDataLoaded(initialFieldValues: InitialFieldValues): InitialFieldValues;
onActiveFieldChange(activeField: ActiveField): { activeField: ActiveField };
onFacetFieldsChange(facetFields: string[]): { facetFields: string[] };
onSortFieldsChange(sortFields: string[]): { sortFields: string[] };
onTitleFieldChange(titleField: string): { titleField: string };
onURLFieldChange(urlField: string): { urlField: string };
}

interface SearchUIValues {
dataLoading: boolean;
validFields: string[];
validSortFields: string[];
validFacetFields: string[];
titleField: string;
urlField: string;
facetFields: string[];
sortFields: string[];
activeField: ActiveField;
}

export const SearchUILogic = kea<MakeLogicType<SearchUIValues, SearchUIActions>>({
path: ['enterprise_search', 'app_search', 'search_ui_logic'],
actions: () => ({
loadFieldData: () => true,
onFieldDataLoaded: (initialFieldValues) => initialFieldValues,
onActiveFieldChange: (activeField) => ({ activeField }),
onFacetFieldsChange: (facetFields) => ({ facetFields }),
onSortFieldsChange: (sortFields) => ({ sortFields }),
onTitleFieldChange: (titleField) => ({ titleField }),
onURLFieldChange: (urlField) => ({ urlField }),
}),
reducers: () => ({
dataLoading: [
true,
{
onFieldDataLoaded: () => false,
},
],
validFields: [[], { onFieldDataLoaded: (_, { validFields }) => validFields }],
validSortFields: [[], { onFieldDataLoaded: (_, { validSortFields }) => validSortFields }],
validFacetFields: [[], { onFieldDataLoaded: (_, { validFacetFields }) => validFacetFields }],
titleField: ['', { onTitleFieldChange: (_, { titleField }) => titleField }],
urlField: ['', { onURLFieldChange: (_, { urlField }) => urlField }],
facetFields: [[], { onFacetFieldsChange: (_, { facetFields }) => facetFields }],
sortFields: [[], { onSortFieldsChange: (_, { sortFields }) => sortFields }],
activeField: [ActiveField.None, { onActiveFieldChange: (_, { activeField }) => activeField }],
}),
listeners: ({ actions }) => ({
loadFieldData: async () => {
const { http } = HttpLogic.values;
const { engineName } = EngineLogic.values;

const url = `/api/app_search/engines/${engineName}/search_ui/field_config`;

try {
const initialFieldValues = await http.get(url);

actions.onFieldDataLoaded(initialFieldValues);
} catch (e) {
flashAPIErrors(e);
}
},
}),
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* 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.
*/

export enum ActiveField {
Title,
Filter,
Sort,
Url,
None,
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,6 @@

import { i18n } from '@kbn/i18n';

import { SchemaType } from './types';

export const fieldTypeSelectOptions = Object.values(SchemaType).map((type) => ({
value: type,
text: type,
}));

export const FIELD_NAME_CORRECT_NOTE = i18n.translate(
'xpack.enterpriseSearch.schema.addFieldModal.fieldNameNote.correct',
{
Expand Down Expand Up @@ -76,10 +69,3 @@ export const ERROR_TABLE_VIEW_LINK = i18n.translate(
defaultMessage: 'View',
}
);

export const RECENTY_ADDED = i18n.translate(
'xpack.enterpriseSearch.schema.existingField.status.recentlyAdded',
{
defaultMessage: 'Recently Added',
}
);
Loading

0 comments on commit ca531a9

Please sign in to comment.