Skip to content

Commit

Permalink
Handle no results cases in search
Browse files Browse the repository at this point in the history
  • Loading branch information
JasonStoltz committed Nov 24, 2020
1 parent 3e4a575 commit 92d1180
Show file tree
Hide file tree
Showing 5 changed files with 341 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* 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.
*/

jest.mock('../hooks', () => ({
useSearchContextActions: jest.fn(() => ({})),
useSearchContextState: jest.fn(() => ({})),
}));

import { useSearchContextState, useSearchContextActions } from '../hooks';

export const setMockSearchContextState = (values: object) => {
(useSearchContextState as jest.Mock).mockImplementation(() => values);
};
export const setMockSearchContextActions = (actions: object) => {
(useSearchContextActions as jest.Mock).mockImplementation(() => actions);
};
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.
*/
const mockAction = jest.fn();

let mockSubcription: (state: object) => void;
const mockDriver = {
state: { foo: 'foo' },
actions: { bar: mockAction },
subscribeToStateChanges: jest.fn().mockImplementation((fn) => {
mockSubcription = fn;
}),
unsubscribeToStateChanges: jest.fn(),
};

jest.mock('react', () => ({
...(jest.requireActual('react') as object),
useContext: jest.fn(() => ({
driver: mockDriver,
})),
}));

import React from 'react';
import { act } from 'react-dom/test-utils';
import { mount } from 'enzyme';

import { useSearchContextState, useSearchContextActions } from './hooks';

describe('hooks', () => {
describe('useSearchContextState', () => {
it('exposes search state', () => {
const TestComponent = () => {
const { foo } = useSearchContextState();
return <div>{foo}</div>;
};

const wrapper = mount(<TestComponent />);
expect(wrapper.text()).toEqual('foo');
});

it('subscribes to state changes', () => {
const TestComponent = () => {
const { foo } = useSearchContextState();
return <div>{foo}</div>;
};

const wrapper = mount(<TestComponent />);

act(() => {
mockSubcription({ foo: 'bar' });
});

expect(wrapper.text()).toEqual('bar');
});

it('unsubscribes to state changes when unmounted', () => {
const TestComponent = () => {
const { foo } = useSearchContextState();
return <div>{foo}</div>;
};

const wrapper = mount(<TestComponent />);

wrapper.unmount();

expect(mockDriver.unsubscribeToStateChanges).toHaveBeenCalled();
});
});

describe('useSearchContextActions', () => {
it('exposes actions', () => {
const TestComponent = () => {
const { bar } = useSearchContextActions();
bar();
return null;
};

mount(<TestComponent />);
expect(mockAction).toHaveBeenCalled();
});
});
});
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 { useContext, useEffect, useState } from 'react';

// @ts-expect-error types are not available for this package yet
import { SearchContext } from '@elastic/react-search-ui';

export const useSearchContextState = () => {
const { driver } = useContext(SearchContext);
const [state, setState] = useState(driver.state);

useEffect(() => {
driver.subscribeToStateChanges((newState: object) => {
setState(newState);
});
return () => {
driver.unsubscribeToStateChanges();
};
}, [state]);

return state;
};

export const useSearchContextActions = () => {
const { driver } = useContext(SearchContext);
return driver.actions;
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { setMockValues } from '../../../../__mocks__/kea.mock';
import { setMockSearchContextState } from './__mocks__/hooks.mock';

import React from 'react';

import { shallow } from 'enzyme';
Expand All @@ -15,12 +18,21 @@ import { ResultView } from './views';
import { SearchExperienceContent } from './search_experience_content';

describe('SearchExperienceContent', () => {
const searchState = {
resultSearchTerm: 'searchTerm',
totalResults: 100,
wasSearched: true,
};
const values = {
engineName: 'engine1',
isMetaEngine: false,
myRole: { canManageEngineDocuments: true },
};

beforeEach(() => {
jest.clearAllMocks();
setMockValues(values);
setMockSearchContextState(searchState);
});

it('renders', () => {
Expand All @@ -47,4 +59,102 @@ describe('SearchExperienceContent', () => {
const pagination = wrapper.find('Pagination').at(0).dive();
expect(pagination.find(EuiFlexGroup).length).toBe(1);
});

it('renders empty if a search was not performed yet', () => {
setMockSearchContextState({
...searchState,
wasSearched: false,
});
const wrapper = shallow(<SearchExperienceContent />);
expect(wrapper.isEmptyRender()).toBe(true);
});

it('renders results if a search was performend and there are more than 0 totalResults', () => {
setMockSearchContextState({
...searchState,
wasSearched: true,
totalResults: 10,
});
const wrapper = shallow(<SearchExperienceContent />);
expect(wrapper.find('[data-test-subj="documentsSearchResults"]').length).toBe(1);
});

it('renders a no results message if a non-empty search was performed and there are no results', () => {
setMockSearchContextState({
...searchState,
resultSearchTerm: 'searchTerm',
wasSearched: true,
totalResults: 0,
});
const wrapper = shallow(<SearchExperienceContent />);
expect(wrapper.find('[data-test-subj="documentsSearchResults"]').length).toBe(0);
expect(wrapper.find('[data-test-subj="documentsSearchNoResults"]').length).toBe(1);
});

describe('when an empty search was performed and there are no results, meaning there are no documents indexed', () => {
beforeEach(() => {
setMockSearchContextState({
...searchState,
resultSearchTerm: '',
wasSearched: true,
totalResults: 0,
});
});
it('renders a no documents message', () => {
const wrapper = shallow(<SearchExperienceContent />);
expect(wrapper.find('[data-test-subj="documentsSearchResults"]').length).toBe(0);
expect(wrapper.find('[data-test-subj="documentsSearchNoDocuments"]').length).toBe(1);
});

it('will include a button to index new documents', () => {
const wrapper = shallow(<SearchExperienceContent />);
const noDocumentsErrorActions: any = wrapper
.find('[data-test-subj="documentsSearchNoDocuments"]')
.prop('actions');

expect(
shallow(noDocumentsErrorActions).find('[data-test-subj="IndexDocumentsButton"]').length
).toBe(1);
});

it('will include a button to documentation if this is a meta engine', () => {
setMockValues({
...values,
isMetaEngine: true,
});

const wrapper = shallow(<SearchExperienceContent />);

const noDocumentsErrorActions: any = wrapper
.find('[data-test-subj="documentsSearchNoDocuments"]')
.prop('actions');

expect(
shallow(noDocumentsErrorActions).find('[data-test-subj="IndexDocumentsButton"]').length
).toBe(0);
expect(
shallow(noDocumentsErrorActions).find('[data-test-subj="documentsSearchDocsLink"]').length
).toBe(1);
});

it('will include a button to documentation if the user cannot manage documents', () => {
setMockValues({
...values,
myRole: { canManageEngineDocuments: false },
});

const wrapper = shallow(<SearchExperienceContent />);

const noDocumentsErrorActions: any = wrapper
.find('[data-test-subj="documentsSearchNoDocuments"]')
.prop('actions');

expect(
shallow(noDocumentsErrorActions).find('[data-test-subj="IndexDocumentsButton"]').length
).toBe(0);
expect(
shallow(noDocumentsErrorActions).find('[data-test-subj="documentsSearchDocsLink"]').length
).toBe(1);
});
});
});
Loading

0 comments on commit 92d1180

Please sign in to comment.