Skip to content

Commit

Permalink
Remaining sample work
Browse files Browse the repository at this point in the history
  • Loading branch information
JasonStoltz committed Apr 1, 2021
1 parent 3a83725 commit b2b11ab
Show file tree
Hide file tree
Showing 7 changed files with 353 additions and 127 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

import '../../../../__mocks__/shallow_useeffect.mock';
import { setMockActions, setMockValues } from '../../../../__mocks__';

import React from 'react';
Expand All @@ -18,9 +19,11 @@ import { SampleResponse } from './sample_response';
describe('SampleResponse', () => {
const actions = {
queryChanged: jest.fn(),
getSearchResults: jest.fn(),
};

const values = {
reducedServerResultFields: {},
query: 'foo',
response: {
bar: 'baz',
Expand All @@ -44,16 +47,29 @@ describe('SampleResponse', () => {
expect(actions.queryChanged).toHaveBeenCalledWith('bar');
});

it('will call getSearchResults with the current value of query and reducedServerResultFields in a useEffect, which updates the displayed response', () => {
const wrapper = shallow(<SampleResponse />);
expect(wrapper.find(EuiFieldSearch).prop('value')).toEqual('foo');
});

it('renders the response from the given user "query" in a code block', () => {
const wrapper = shallow(<SampleResponse />);
expect(wrapper.find(EuiCodeBlock).prop('children')).toEqual('{\n "bar": "baz"\n}');
});

it('renders an empty string the code block if no response exists yet', () => {
it('renders a plain old string in the code block if the response is a string', () => {
setMockValues({
response: 'No results.',
});
const wrapper = shallow(<SampleResponse />);
expect(wrapper.find(EuiCodeBlock).prop('children')).toEqual('No results.');
});

it('will not render a code block at all if there is no response yet', () => {
setMockValues({
response: null,
});
const wrapper = shallow(<SampleResponse />);
expect(wrapper.find(EuiCodeBlock).prop('children')).toEqual('');
expect(wrapper.find(EuiCodeBlock).exists()).toEqual(false);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

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

import { useActions, useValues } from 'kea';

Expand All @@ -20,11 +20,19 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';

import { ResultSettingsLogic } from '../result_settings_logic';

import { SampleResponseLogic } from './sample_response_logic';

export const SampleResponse: React.FC = () => {
const { reducedServerResultFields } = useValues(ResultSettingsLogic);

const { query, response } = useValues(SampleResponseLogic);
const { queryChanged } = useActions(SampleResponseLogic);
const { queryChanged, getSearchResults } = useActions(SampleResponseLogic);

useEffect(() => {
getSearchResults(query, reducedServerResultFields);
}, [query, reducedServerResultFields]);

return (
<EuiPanel hasShadow>
Expand Down Expand Up @@ -54,11 +62,11 @@ export const SampleResponse: React.FC = () => {
data-test-subj="ResultSettingsQuerySampleResponse"
/>
<EuiSpacer />
<EuiCodeBlock language="json" whiteSpace="pre-wrap">
{/* TODO No results messsage */}
{/* TODO Query on load */}
{response ? JSON.stringify(response, null, 2) : ''}
</EuiCodeBlock>
{!!response && (
<EuiCodeBlock language="json" whiteSpace="pre-wrap">
{typeof response === 'string' ? response : JSON.stringify(response, null, 2)}
</EuiCodeBlock>
)}
</EuiPanel>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,22 @@
* 2.0.
*/

import { LogicMounter } from '../../../../__mocks__';
import { LogicMounter, mockHttpValues } from '../../../../__mocks__';
import '../../../__mocks__/engine_logic.mock';

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

import { flashAPIErrors } from '../../../../shared/flash_messages';

import { SampleResponseLogic } from './sample_response_logic';

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

const DEFAULT_VALUES = {
query: '',
response: null,
isLoading: false,
};

beforeEach(() => {
Expand All @@ -33,113 +36,203 @@ describe('SampleResponseLogic', () => {

describe('actions', () => {
describe('queryChanged', () => {
it('updates query and sets isLoading to true', () => {
it('updates the query', () => {
mount({
query: {},
isLoading: false,
query: '',
});

SampleResponseLogic.actions.queryChanged('foo');

expect(SampleResponseLogic.values).toEqual({
...DEFAULT_VALUES,
query: 'foo',
isLoading: true,
});
});
});

describe('getSearchResultsSuccess', () => {
it('sets the response from a search API request and sets isLoading to false', () => {
it('sets the response from a search API request', () => {
mount({
response: null,
isLoading: true,
});

SampleResponseLogic.actions.getSearchResultsSuccess({});

expect(SampleResponseLogic.values).toEqual({
...DEFAULT_VALUES,
response: {},
isLoading: false,
});
});

it('sets the response to null if no response is passed', () => {
mount({
response: null,
});

SampleResponseLogic.actions.getSearchResultsSuccess();

expect(SampleResponseLogic.values).toEqual({
...DEFAULT_VALUES,
response: null,
});
});
});

describe('getSearchResultsFailure', () => {
it('sets isLoading to false', () => {
it('sets a string response from a search API request', () => {
mount({
isLoading: true,
response: null,
});

SampleResponseLogic.actions.getSearchResultsFailure('An error occured.');

expect(SampleResponseLogic.values).toEqual({
...DEFAULT_VALUES,
response: 'An error occured.',
});
});

it('sets the response to null if no response is passed', () => {
mount({
response: null,
});

SampleResponseLogic.actions.getSearchResultsFailure();

expect(SampleResponseLogic.values).toEqual({
...DEFAULT_VALUES,
isLoading: false,
response: null,
});
});
});
});

describe('listeners', () => {
describe('queryChanged', () => {
// TODO it('makes an API request')
describe('getSearchResults', () => {
beforeAll(() => jest.useFakeTimers());
afterAll(() => jest.useRealTimers());

it('calls getSearchResultsSuccess with the result of the response from the search API request', async () => {
it('makes a search API request and calls getSearchResultsSuccess with the first result of the response', async () => {
mount();
jest.spyOn(SampleResponseLogic.actions, 'getSearchResultsSuccess');

SampleResponseLogic.actions.queryChanged('foo');
http.post.mockReturnValue(
Promise.resolve({
results: [
{ id: { raw: 'foo' }, _meta: {} },
{ id: { raw: 'bar' }, _meta: {} },
{ id: { raw: 'baz' }, _meta: {} },
],
})
);

SampleResponseLogic.actions.getSearchResults('foo', { foo: { raw: true } });
jest.runAllTimers();
await nextTick();

expect(SampleResponseLogic.actions.getSearchResultsSuccess).toHaveBeenCalledWith({
visitors: {
raw: 776218,
},
nps_image_url: {
raw:
'https://www.nps.gov/common/uploads/banner_image/imr/homepage/9E7FC0DB-1DD8-B71B-0BC3880DC2250415.jpg',
},
square_km: {
raw: 1366.2,
},
world_heritage_site: {
raw: 'false',
},
date_established: {
raw: '1964-09-12T05:00:00+00:00',
},
image_url: {
raw:
'https://storage.googleapis.com/public-demo-assets.swiftype.info/swiftype-dot-com-search-ui-national-parks-demo/9E7FC0DB-1DD8-B71B-0BC3880DC2250415.jpg',
},
description: {
raw:
'This landscape was eroded into a maze of canyons, buttes, and mesas by the combined efforts of the Colorado River, Green River, and their tributaries, which divide the park into three districts. The park also contains rock pinnacles and arches, as well as artifacts from Ancient Pueblo peoples.',
},
location: {
raw: '38.2,-109.93',
},
acres: {
raw: '337597.83',
},
title: {
raw: 'Canyonlands',
},
nps_link: {
raw: 'https://www.nps.gov/cany/index.htm',
},
states: {
raw: ['Utah'],
},
id: {
raw: 'park_canyonlands',
},
// Note that the _meta field was stripped from the result
id: { raw: 'foo' },
});
});

// TODO it('handles errors')
it('calls getSearchResultsSuccess with a "No Results." message if there are no results', async () => {
mount();
jest.spyOn(SampleResponseLogic.actions, 'getSearchResultsSuccess');

http.post.mockReturnValue(
Promise.resolve({
results: [],
})
);

SampleResponseLogic.actions.getSearchResults('foo', { foo: { raw: true } });
jest.runAllTimers();
await nextTick();

expect(SampleResponseLogic.actions.getSearchResultsSuccess).toHaveBeenCalledWith(
'No results.'
);
});

it('handles 500 errors by setting a generic error response and showing a flash message error', async () => {
mount();
jest.spyOn(SampleResponseLogic.actions, 'getSearchResultsFailure');

const error = {
response: {
status: 500,
},
};

http.post.mockReturnValueOnce(Promise.reject(error));

SampleResponseLogic.actions.getSearchResults('foo', { foo: { raw: true } });
jest.runAllTimers();
await nextTick();

expect(flashAPIErrors).toHaveBeenCalledWith(error);
expect(SampleResponseLogic.actions.getSearchResultsFailure).toHaveBeenCalledWith(
'An error occured.'
);
});

it('handles 400 errors by setting the response message, but does not show a flash error message', async () => {
mount();
jest.spyOn(SampleResponseLogic.actions, 'getSearchResultsFailure');

http.post.mockReturnValueOnce(
Promise.reject({
response: {
status: 400,
},
body: {
message: 'A validation error occurred.',
},
})
);

SampleResponseLogic.actions.getSearchResults('foo', { foo: { raw: true } });
jest.runAllTimers();
await nextTick();

expect(SampleResponseLogic.actions.getSearchResultsFailure).toHaveBeenCalledWith(
'A validation error occurred.'
);
});

it('sets a generic message on a 400 error if no custom message is provided in the response', async () => {
mount();
jest.spyOn(SampleResponseLogic.actions, 'getSearchResultsFailure');

http.post.mockReturnValueOnce(
Promise.reject({
response: {
status: 400,
},
})
);

SampleResponseLogic.actions.getSearchResults('foo', { foo: { raw: true } });
jest.runAllTimers();
await nextTick();

expect(SampleResponseLogic.actions.getSearchResultsFailure).toHaveBeenCalledWith(
'An error occured.'
);
});

it('does nothing if an empty object is passed for the resultFields parameter', async () => {
mount();
jest.spyOn(SampleResponseLogic.actions, 'getSearchResultsSuccess');

SampleResponseLogic.actions.getSearchResults('foo', {});

jest.runAllTimers();
await nextTick();

expect(SampleResponseLogic.actions.getSearchResultsSuccess).not.toHaveBeenCalled();
});
});
});
});
Loading

0 comments on commit b2b11ab

Please sign in to comment.