From 31cc2aa242802aa60f384d97293f9d7177115462 Mon Sep 17 00:00:00 2001 From: Davey Holler Date: Fri, 2 Apr 2021 16:39:19 -0700 Subject: [PATCH 1/5] Starting work on result component --- .../app_search/components/result/index.ts | 1 + .../app_search/components/result/result.scss | 26 +--- .../app_search/components/result/result.tsx | 127 ++++++++---------- .../components/result/result_field.scss | 10 ++ .../components/result/result_field.tsx | 7 +- .../components/result/result_header.scss | 2 - .../components/result/result_header.tsx | 70 +++++++--- .../components/result/result_header_item.scss | 22 ++- .../components/result/result_header_item.tsx | 44 ++++-- .../components/result/result_token.tsx | 30 +++++ .../app_search/components/result/types.ts | 4 +- 11 files changed, 203 insertions(+), 140 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_token.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/index.ts index 89909c1e51d3ff..a7eed3b95e6fa7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/index.ts @@ -6,4 +6,5 @@ */ export { ResultFieldValue } from './result_field_value'; +export { ResultToken } from './result_token'; export { Result } from './result'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.scss index 5f1b165f2c362c..3132894ddc7a14 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.scss +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.scss @@ -6,6 +6,7 @@ 'drag content actions' 'drag toggle actions'; overflow: hidden; // Prevents child background-colors from clipping outside of panel border-radius + border: $euiBorderThin; // TODO: Remove after EUI version is bumped beyond 31.8.0 &__content { grid-area: content; @@ -44,9 +45,13 @@ display: flex; justify-content: center; align-items: center; - width: $euiSizeL * 2; + width: $euiSize * 2; border-left: $euiBorderThin; + &:first-child { + border-left: none; + } + &:hover, &:focus { background-color: $euiPageBackgroundColor; @@ -62,22 +67,3 @@ border-right: $euiBorderThin; } } - -/** - * CSS for hover specific logic - * It's mildly horrific, so I pulled it out to its own section here - */ - -.appSearchResult--link { - &:hover, - &:focus { - @include euiSlightShadowHover; - } -} -.appSearchResult__content--link:hover { - cursor: pointer; - - & ~ .appSearchResult__actionButtons .appSearchResult__actionButton--link { - background-color: $euiPageBackgroundColor; - } -} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx index 89208a041af351..ace16bddc8e585 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx @@ -8,16 +8,15 @@ import React, { useState, useMemo } from 'react'; import { DraggableProvidedDragHandleProps } from 'react-beautiful-dnd'; -import classNames from 'classnames'; - import './result.scss'; -import { EuiPanel, EuiIcon } from '@elastic/eui'; +import { EuiButtonIcon, EuiPanel, EuiFlexGroup, EuiFlexItem, EuiIcon } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ReactRouterHelper } from '../../../shared/react_router_helpers/eui_components'; import { Schema } from '../../../shared/types'; + import { ENGINE_DOCUMENT_DETAIL_PATH } from '../../routes'; import { generateEncodedPath } from '../../utils/encode_path_params'; @@ -56,34 +55,53 @@ export const Result: React.FC = ({ [result] ); const numResults = resultFields.length; - const typeForField = (fieldName: string) => { - if (schemaForTypeHighlights) return schemaForTypeHighlights[fieldName]; - }; - const documentLink = generateEncodedPath(ENGINE_DOCUMENT_DETAIL_PATH, { engineName: resultMeta.engine, documentId: resultMeta.id, }); - const conditionallyLinkedArticle = (children: React.ReactNode) => { - return shouldLinkToDetailPage ? ( - -
- {children} -
-
- ) : ( -
{children}
- ); + + const typeForField = (fieldName: string) => { + if (schemaForTypeHighlights) return schemaForTypeHighlights[fieldName]; }; - const classes = classNames('appSearchResult', { - 'appSearchResult--link': shouldLinkToDetailPage, - }); + const ResultActions = () => { + if (!shouldLinkToDetailPage && !actions.length) return null; + return ( + + + {shouldLinkToDetailPage && ( + + + + + + )} + {actions.map(({ onClick, title, iconType, iconColor }) => ( + + + + ))} + + + ); + }; return ( = ({ )} - {conditionallyLinkedArticle( - <> - - {resultFields - .slice(0, isOpen ? resultFields.length : RESULT_CUTOFF) - .map(([field, value]: [string, FieldValue]) => ( - - ))} - - )} +
+ } + /> + {resultFields + .slice(0, isOpen ? resultFields.length : RESULT_CUTOFF) + .map(([field, value]: [string, FieldValue]) => ( + + ))} +
{numResults > RESULT_CUTOFF && ( )} -
- {shouldLinkToDetailPage && ( - - - - - - )} - {actions.map(({ onClick, title, iconType, iconColor }) => ( - - ))} -
); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.scss index 80d60e2de67e2f..443c130548f6b5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.scss +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.scss @@ -14,6 +14,16 @@ } } + &__key { + display: flex; + align-items: center; + @include euiCodeFont; + + .euiToken { + margin-right: $euiSizeS; + } + } + &__value { padding-left: $euiSize; overflow: hidden; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.tsx index 003810ec40a8d1..9b78d769d2f30d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { FieldType, Raw, Snippet } from './types'; -import { ResultFieldValue } from '.'; +import { ResultFieldValue, ResultToken } from '.'; import './result_field.scss'; @@ -23,7 +23,10 @@ interface Props { export const ResultField: React.FC = ({ field, raw, snippet, type }) => { return (
-
{field}
+
+ {type && } + {field} +
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.scss index 73372d7c4aca07..cd1042998dd347 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.scss +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.scss @@ -1,7 +1,5 @@ .appSearchResultHeader { display: flex; - justify-content: space-between; - align-items: flex-start; margin-bottom: $euiSizeS; @include euiBreakpoint('xs') { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.tsx index 550093a8cd904d..0cafb0d8a8deca 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.tsx @@ -7,6 +7,11 @@ import React from 'react'; +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; + +import { ENGINE_DOCUMENT_DETAIL_PATH } from '../../routes'; +import { generateEncodedPath } from '../../utils/encode_path_params'; + import { ResultHeaderItem } from './result_header_item'; import { ResultMeta } from './types'; @@ -16,33 +21,58 @@ interface Props { showScore: boolean; isMetaEngine: boolean; resultMeta: ResultMeta; + actions?: React.ReactNode; + shouldLinkToDetailPage: boolean; } -export const ResultHeader: React.FC = ({ showScore, resultMeta, isMetaEngine }) => { +export const ResultHeader: React.FC = ({ + showScore, + resultMeta, + isMetaEngine, + actions, + shouldLinkToDetailPage, +}) => { + const documentLink = generateEncodedPath(ENGINE_DOCUMENT_DETAIL_PATH, { + engineName: resultMeta.engine, + documentId: resultMeta.id, + }); + return ( -
- {showScore && ( -
+
+ + -
- )} - -
+ + {/* Score */} + {showScore && ( + + + + )} + {/* Engine Name */} {isMetaEngine && ( - + + + )} - -
+ {actions} +
); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.scss index f1e9343530af38..438f1f99c65d16 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.scss +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.scss @@ -1,16 +1,12 @@ -.appSearchResultHeaderItem { - display: flex; +.euiFlexItem:not(:first-child):not(:last-child) .appSearchResultHeaderItem { + padding-right: .75rem; + box-shadow: inset -1px 0 0 0 $euiBorderColor; +} - &__key, - &__value { - line-height: $euiLineHeight; - font-size: $euiFontSizeXS; - } +.appSearchResultHeaderItem { + @include euiCodeFont; - &__key { - text-transform: uppercase; - font-weight: $euiFontWeightLight; - color: $euiColorDarkShade; - margin-right: $euiSizeXS; + &__score { + color: $euiColorSuccessText; } -} +} \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.tsx index cda56fbc4797c3..545b85c17a529d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.tsx @@ -9,17 +9,20 @@ import React from 'react'; import './result_header_item.scss'; +import { ReactRouterHelper } from '../../../shared/react_router_helpers/eui_components'; + import { TruncatedContent } from '../../../shared/truncate'; interface Props { field: string; value?: string | number; type: 'id' | 'score' | 'string'; + href?: string; } const MAX_CHARACTER_LENGTH = 30; -export const ResultHeaderItem: React.FC = ({ field, type, value }) => { +export const ResultHeaderItem: React.FC = ({ field, type, value, href }) => { let formattedValue = '-'; if (typeof value === 'string') { formattedValue = value; @@ -27,19 +30,32 @@ export const ResultHeaderItem: React.FC = ({ field, type, value }) => { formattedValue = parseFloat((value as number).toFixed(2)).toString(); } + const HeaderItemContent = () => ( + + ); + return ( -
-
- -
-
- -
-
+ + +   + {href ? ( + + + + + + ) : ( + + )} + ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_token.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_token.tsx new file mode 100644 index 00000000000000..773fcd19ce9ea1 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_token.tsx @@ -0,0 +1,30 @@ +/* + * 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 React from 'react'; + +import { EuiToken } from '@elastic/eui'; + +import { FieldType } from './types'; + +interface Props { + fieldType: FieldType; +} + +const fieldTypeToTokenMap = { + text: 'tokenString', + string: 'tokenString', + number: 'tokenNumber', + float: 'tokenNumber', + location: 'tokenGeo', + geolocation: 'tokenGeo', + date: 'tokenDate', +}; + +export const ResultToken: React.FC = ({ fieldType }) => { + return ; +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/types.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/types.ts index 96a135b0db36ea..7a297f98139f36 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/types.ts @@ -7,6 +7,8 @@ import { InternalSchemaTypes, SchemaTypes } from '../../../shared/types'; +import { EuiIconProps } from '@elastic/eui'; + export type FieldType = InternalSchemaTypes | SchemaTypes; export type Raw = string | string[] | number | number[]; @@ -38,5 +40,5 @@ export interface ResultAction { onClick(): void; title: string; iconType: string; - iconColor?: string; + iconColor?: EuiIconProps['color']; } From 97cbb6fe6674d2e6f3e2d5ae647bb02b62bbcbe8 Mon Sep 17 00:00:00 2001 From: Jason Stoltzfus Date: Wed, 7 Apr 2021 13:55:50 -0400 Subject: [PATCH 2/5] Write tests --- .../app_search/components/library/library.tsx | 2 +- .../components/result/result.test.tsx | 84 ++++++++++--------- .../app_search/components/result/result.tsx | 3 +- .../components/result/result_header.test.tsx | 16 ++++ .../result/result_header_item.test.tsx | 30 +++++-- .../components/result/result_token.test.tsx | 28 +++++++ 6 files changed, 113 insertions(+), 50 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_token.test.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/library/library.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/library/library.tsx index ad693628d911e4..4d6bca4305a3a6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/library/library.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/library/library.tsx @@ -221,7 +221,7 @@ export const Library: React.FC = () => {

With custom actions and a link

- + diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.test.tsx index 15c9ee2967d3e3..56ad1ca3fbdb1f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.test.tsx @@ -10,9 +10,8 @@ import { DraggableProvidedDragHandleProps } from 'react-beautiful-dnd'; import { shallow, ShallowWrapper } from 'enzyme'; -import { EuiPanel } from '@elastic/eui'; +import { EuiButtonIcon, EuiPanel } from '@elastic/eui'; -import { ReactRouterHelper } from '../../../shared/react_router_helpers/eui_components'; import { SchemaTypes } from '../../../shared/types'; import { Result } from './result'; @@ -64,37 +63,18 @@ describe('Result', () => { ]); }); - it('passes showScore, resultMeta, and isMetaEngine to ResultHeader', () => { + it('renders a header', () => { const wrapper = shallow(); - expect(wrapper.find(ResultHeader).props()).toEqual({ - isMetaEngine: true, - showScore: true, - resultMeta: { - id: '1', - score: 100, - engine: 'my-engine', - }, - }); - }); - - describe('document detail link', () => { - it('will render a link if shouldLinkToDetailPage is true', () => { - const wrapper = shallow(); - wrapper.find(ReactRouterHelper).forEach((link) => { - expect(link.prop('to')).toEqual('/engines/my-engine/documents/1'); - }); - expect(wrapper.hasClass('appSearchResult--link')).toBe(true); - expect(wrapper.find('.appSearchResult__content--link').exists()).toBe(true); - expect(wrapper.find('.appSearchResult__actionButton--link').exists()).toBe(true); - }); - - it('will not render a link if shouldLinkToDetailPage is not set', () => { - const wrapper = shallow(); - expect(wrapper.find(ReactRouterHelper).exists()).toBe(false); - expect(wrapper.hasClass('appSearchResult--link')).toBe(false); - expect(wrapper.find('.appSearchResult__content--link').exists()).toBe(false); - expect(wrapper.find('.appSearchResult__actionButton--link').exists()).toBe(false); - }); + const header = wrapper.find(ResultHeader); + expect(header.exists()).toBe(true); + expect(header.prop('isMetaEngine')).toBe(true); // passed through from props + expect(header.prop('showScore')).toBe(true); // passed through from props + expect(header.prop('shouldLinkToDetailPage')).toBe(false); // passed through from props + expect(header.prop('resultMeta')).toEqual({ + id: '1', + score: 100, + engine: 'my-engine', + }); // passed through from meta in result prop }); describe('actions', () => { @@ -109,24 +89,48 @@ describe('Result', () => { title: 'Bookmark', onClick: jest.fn(), iconType: 'starFilled', - iconColor: 'primary', + iconColor: '', }, ]; - it('will render an action button for each action passed', () => { + it('will render an action button in the header for each action passed', () => { const wrapper = shallow(); - expect(wrapper.find('.appSearchResult__actionButton')).toHaveLength(2); - - wrapper.find('.appSearchResult__actionButton').first().simulate('click'); + const header = wrapper.find(ResultHeader); + const renderedActions = shallow(header.prop('actions') as any); + const buttons = renderedActions.find(EuiButtonIcon); + expect(buttons).toHaveLength(2); + + // console.log(buttons.first().props()); + expect(buttons.first().prop('iconType')).toEqual('eyeClosed'); + expect(buttons.first().prop('color')).toEqual('danger'); + buttons.first().simulate('click'); expect(actions[0].onClick).toHaveBeenCalled(); - wrapper.find('.appSearchResult__actionButton').last().simulate('click'); + expect(buttons.last().prop('iconType')).toEqual('starFilled'); + // Note that no iconColor was passed so it was defaulted to primary + expect(buttons.last().prop('color')).toEqual('primary'); + buttons.last().simulate('click'); expect(actions[1].onClick).toHaveBeenCalled(); }); - it('will render custom actions seamlessly next to the document detail link', () => { + it('will render a document detail link as the first action if shouldLinkToDetailPage is passed', () => { const wrapper = shallow(); - expect(wrapper.find('.appSearchResult__actionButton')).toHaveLength(3); + const header = wrapper.find(ResultHeader); + const renderedActions = shallow(header.prop('actions') as any); + const buttons = renderedActions.find(EuiButtonIcon); + + // In addition to the 2 actions passed, we also have an action + expect(buttons).toHaveLength(3); + + expect(buttons.first().prop('data-test-subj')).toEqual('DocumentDetailLink'); + }); + + it('will not render anything if no actions are passed and shouldLinkToDetailPage is false', () => { + const wrapper = shallow(); + const header = wrapper.find(ResultHeader); + const renderedActions = shallow(header.prop('actions') as any); + const buttons = renderedActions.find(EuiButtonIcon); + expect(buttons).toHaveLength(0); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx index ace16bddc8e585..f3a17a6555b394 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx @@ -74,6 +74,7 @@ export const Result: React.FC = ({ = ({ diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.test.tsx index dcefd0f6bc0b05..80cff9b96a3cad 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.test.tsx @@ -30,6 +30,22 @@ describe('ResultHeader', () => { ); expect(wrapper.find('[data-test-subj="ResultId"]').prop('value')).toEqual('1'); + expect(wrapper.find('[data-test-subj="ResultId"]').prop('href')).toBeUndefined(); + }); + + it('renders id as a link if shouldLinkToDetailPage is true', () => { + const wrapper = shallow( + + ); + expect(wrapper.find('[data-test-subj="ResultId"]').prop('value')).toEqual('1'); + expect(wrapper.find('[data-test-subj="ResultId"]').prop('href')).toEqual( + '/engines/my-engine/documents/1' + ); }); describe('score', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.test.tsx index 52fa81943bb2e8..e0407b4db7f251 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.test.tsx @@ -7,15 +7,14 @@ import React from 'react'; -import { mount } from 'enzyme'; +import { shallow, mount } from 'enzyme'; import { ResultHeaderItem } from './result_header_item'; describe('ResultHeaderItem', () => { it('renders', () => { const wrapper = mount(); - expect(wrapper.find('.appSearchResultHeaderItem__key').text()).toEqual('id'); - expect(wrapper.find('.appSearchResultHeaderItem__value').text()).toEqual('001'); + expect(wrapper.find('.appSearchResultHeaderItem').text()).toContain('001'); }); it('will truncate long field names', () => { @@ -26,7 +25,7 @@ describe('ResultHeaderItem', () => { type="string" /> ); - expect(wrapper.find('.appSearchResultHeaderItem__key').text()).toEqual( + expect(wrapper.find('.appSearchResultHeaderItem').text()).toContain( 'a-really-really-really-really-…' ); }); @@ -35,7 +34,7 @@ describe('ResultHeaderItem', () => { const wrapper = mount( ); - expect(wrapper.find('.appSearchResultHeaderItem__value').text()).toEqual( + expect(wrapper.find('.appSearchResultHeaderItem').text()).toContain( 'a-really-really-really-really-…' ); }); @@ -44,18 +43,33 @@ describe('ResultHeaderItem', () => { const wrapper = mount( ); - expect(wrapper.find('.appSearchResultHeaderItem__value').text()).toEqual( + expect(wrapper.find('.appSearchResultHeaderItem').text()).toContain( '…lly-really-really-really-value' ); }); it('will round any numeric values that are passed in to 2 decimals, regardless of the explicit "type" passed', () => { const wrapper = mount(); - expect(wrapper.find('.appSearchResultHeaderItem__value').text()).toEqual('5.19'); + expect(wrapper.find('.appSearchResultHeaderItem').text()).toContain('5.19'); }); it('if the value passed in is undefined, it will render "-"', () => { const wrapper = mount(); - expect(wrapper.find('.appSearchResultHeaderItem__value').text()).toEqual('-'); + expect(wrapper.find('.appSearchResultHeaderItem').text()).toContain('-'); + }); + + it('it will add a "score" class if the "type" passed is "score"', () => { + const wrapper = shallow(); + expect( + wrapper.find('.appSearchResultHeaderItem').hasClass('appSearchResultHeaderItem__score') + ).toBe(true); + }); + + it('it will render as a link if an href is passed', () => { + const wrapper = shallow( + + ); + expect(wrapper.find('ReactRouterHelper').exists()).toBe(true); + expect(wrapper.find('ReactRouterHelper').prop('to')).toBe('http://www.example.com'); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_token.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_token.test.tsx new file mode 100644 index 00000000000000..d50b35198acb96 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_token.test.tsx @@ -0,0 +1,28 @@ +/* + * 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 React from 'react'; + +import { shallow } from 'enzyme'; + +import { EuiToken } from '@elastic/eui'; + +import { ResultToken } from './result_token'; + +describe('ResultToken', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('render a token icon based on the provided field type', () => { + expect( + shallow() + .find(EuiToken) + .prop('iconType') + ).toBe('tokenString'); + }); +}); From cd5488eeef4f0a6e2a4bccc8e8e6a02066e1602b Mon Sep 17 00:00:00 2001 From: Jason Stoltzfus Date: Wed, 7 Apr 2021 14:25:19 -0400 Subject: [PATCH 3/5] Fix types --- .../app_search/components/curations/constants.ts | 9 +++++---- .../app_search/components/library/library.tsx | 3 ++- .../applications/app_search/components/result/result.tsx | 1 + .../applications/app_search/components/result/types.ts | 6 +++--- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/constants.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/constants.ts index 57af8cada9890b..99f3d340f84305 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/constants.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/constants.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { EuiButtonIconColor } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; export const CURATIONS_TITLE = i18n.translate( @@ -49,26 +50,26 @@ export const PROMOTE_DOCUMENT_ACTION = { defaultMessage: 'Promote this result', }), iconType: 'starPlusEmpty', - iconColor: 'primary', + iconColor: 'primary' as EuiButtonIconColor, }; export const DEMOTE_DOCUMENT_ACTION = { title: i18n.translate('xpack.enterpriseSearch.appSearch.engine.curations.demoteButtonLabel', { defaultMessage: 'Demote this result', }), iconType: 'starMinusFilled', - iconColor: 'primary', + iconColor: 'primary' as EuiButtonIconColor, }; export const HIDE_DOCUMENT_ACTION = { title: i18n.translate('xpack.enterpriseSearch.appSearch.engine.curations.hideButtonLabel', { defaultMessage: 'Hide this result', }), iconType: 'eyeClosed', - iconColor: 'danger', + iconColor: 'danger' as EuiButtonIconColor, }; export const SHOW_DOCUMENT_ACTION = { title: i18n.translate('xpack.enterpriseSearch.appSearch.engine.curations.showButtonLabel', { defaultMessage: 'Show this result', }), iconType: 'eye', - iconColor: 'primary', + iconColor: 'primary' as EuiButtonIconColor, }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/library/library.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/library/library.tsx index 4d6bca4305a3a6..9ad32c6e48632e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/library/library.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/library/library.tsx @@ -16,6 +16,7 @@ import { EuiDragDropContext, EuiDroppable, EuiDraggable, + EuiButtonIconColor, } from '@elastic/eui'; import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; @@ -78,7 +79,7 @@ export const Library: React.FC = () => { title: 'Fill this action button', onClick: () => setIsActionButtonFilled(!isActionButtonFilled), iconType: isActionButtonFilled ? 'starFilled' : 'starEmpty', - iconColor: 'primary', + iconColor: 'primary' as EuiButtonIconColor, }, ]; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx index f3a17a6555b394..71d9f39d802d5b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx @@ -11,6 +11,7 @@ import { DraggableProvidedDragHandleProps } from 'react-beautiful-dnd'; import './result.scss'; import { EuiButtonIcon, EuiPanel, EuiFlexGroup, EuiFlexItem, EuiIcon } from '@elastic/eui'; + import { i18n } from '@kbn/i18n'; import { ReactRouterHelper } from '../../../shared/react_router_helpers/eui_components'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/types.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/types.ts index 7a297f98139f36..638a76511deee4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/types.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { InternalSchemaTypes, SchemaTypes } from '../../../shared/types'; +import { EuiButtonIconColor } from '@elastic/eui'; -import { EuiIconProps } from '@elastic/eui'; +import { InternalSchemaTypes, SchemaTypes } from '../../../shared/types'; export type FieldType = InternalSchemaTypes | SchemaTypes; @@ -40,5 +40,5 @@ export interface ResultAction { onClick(): void; title: string; iconType: string; - iconColor?: EuiIconProps['color']; + iconColor?: EuiButtonIconColor; } From b2af29b1d5e1c892adbe123f422e6d4d69c473e1 Mon Sep 17 00:00:00 2001 From: Jason Stoltzfus Date: Wed, 7 Apr 2021 14:36:56 -0400 Subject: [PATCH 4/5] Cleanup --- .../applications/app_search/components/result/result.test.tsx | 3 +-- .../app_search/components/result/result_header.tsx | 1 - .../app_search/components/result/result_header_item.scss | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.test.tsx index 56ad1ca3fbdb1f..ac1bb0348d2052 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.test.tsx @@ -100,7 +100,6 @@ describe('Result', () => { const buttons = renderedActions.find(EuiButtonIcon); expect(buttons).toHaveLength(2); - // console.log(buttons.first().props()); expect(buttons.first().prop('iconType')).toEqual('eyeClosed'); expect(buttons.first().prop('color')).toEqual('danger'); buttons.first().simulate('click'); @@ -119,7 +118,7 @@ describe('Result', () => { const renderedActions = shallow(header.prop('actions') as any); const buttons = renderedActions.find(EuiButtonIcon); - // In addition to the 2 actions passed, we also have an action + // In addition to the 2 actions passed, we also have a link action expect(buttons).toHaveLength(3); expect(buttons.first().prop('data-test-subj')).toEqual('DocumentDetailLink'); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.tsx index 0cafb0d8a8deca..35227716715612 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.tsx @@ -60,7 +60,6 @@ export const ResultHeader: React.FC = ({ /> )} - {/* Engine Name */} {isMetaEngine && ( Date: Thu, 8 Apr 2021 09:43:36 -0400 Subject: [PATCH 5/5] Fix type errors --- .../app_search/components/result/result.test.tsx | 6 +++--- .../app_search/components/result/result_header.tsx | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.test.tsx index ac1bb0348d2052..3e83717bf93559 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.test.tsx @@ -10,7 +10,7 @@ import { DraggableProvidedDragHandleProps } from 'react-beautiful-dnd'; import { shallow, ShallowWrapper } from 'enzyme'; -import { EuiButtonIcon, EuiPanel } from '@elastic/eui'; +import { EuiButtonIcon, EuiPanel, EuiButtonIconColor } from '@elastic/eui'; import { SchemaTypes } from '../../../shared/types'; @@ -83,13 +83,13 @@ describe('Result', () => { title: 'Hide', onClick: jest.fn(), iconType: 'eyeClosed', - iconColor: 'danger', + iconColor: 'danger' as EuiButtonIconColor, }, { title: 'Bookmark', onClick: jest.fn(), iconType: 'starFilled', - iconColor: '', + iconColor: undefined, }, ]; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.tsx index 35227716715612..93a684b1968a2e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.tsx @@ -22,7 +22,7 @@ interface Props { isMetaEngine: boolean; resultMeta: ResultMeta; actions?: React.ReactNode; - shouldLinkToDetailPage: boolean; + shouldLinkToDetailPage?: boolean; } export const ResultHeader: React.FC = ({ @@ -30,7 +30,7 @@ export const ResultHeader: React.FC = ({ resultMeta, isMetaEngine, actions, - shouldLinkToDetailPage, + shouldLinkToDetailPage = false, }) => { const documentLink = generateEncodedPath(ENGINE_DOCUMENT_DETAIL_PATH, { engineName: resultMeta.engine, @@ -49,7 +49,6 @@ export const ResultHeader: React.FC = ({ type="id" /> - {/* Score */} {showScore && (