From 8a644dbc0fd1809c00572679f3ae71c5d1ed01b4 Mon Sep 17 00:00:00 2001 From: Constance Chen Date: Fri, 29 Jan 2021 15:26:39 -0800 Subject: [PATCH 1/8] Add encodePathParam helper + update components that need it - Primarily document URLs & analytics queries (which uses generateEnginePath) --- .../app_search/components/engine/utils.ts | 4 +++- .../app_search/components/result/result.tsx | 12 +++++++---- .../utils/encode_path_params/index.test.ts | 20 +++++++++++++++++++ .../utils/encode_path_params/index.ts | 15 ++++++++++++++ 4 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/utils/encode_path_params/index.test.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/utils/encode_path_params/index.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/utils.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/utils.ts index b7efcbb6e6b27a..4fd9d4cef8fa41 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/utils.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/utils.ts @@ -6,6 +6,8 @@ import { generatePath } from 'react-router-dom'; +import { encodePathParams } from '../../utils/encode_path_params'; + import { EngineLogic } from './'; /** @@ -13,5 +15,5 @@ import { EngineLogic } from './'; */ export const generateEnginePath = (path: string, pathParams: object = {}) => { const { engineName } = EngineLogic.values; - return generatePath(path, { engineName, ...pathParams }); + return generatePath(path, encodePathParams({ engineName, ...pathParams })); }; 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 a3935bb782f906..3837e65b3a376c 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 @@ -14,6 +14,7 @@ import { EuiPanel, EuiIcon } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ReactRouterHelper } from '../../../shared/react_router_helpers/eui_components'; +import { encodePathParams } from '../../utils/encode_path_params'; import { ENGINE_DOCUMENT_DETAIL_PATH } from '../../routes'; import { Schema } from '../../../shared/types'; @@ -52,10 +53,13 @@ export const Result: React.FC = ({ if (schemaForTypeHighlights) return schemaForTypeHighlights[fieldName]; }; - const documentLink = generatePath(ENGINE_DOCUMENT_DETAIL_PATH, { - engineName: resultMeta.engine, - documentId: resultMeta.id, - }); + const documentLink = generatePath( + ENGINE_DOCUMENT_DETAIL_PATH, + encodePathParams({ + engineName: resultMeta.engine, + documentId: resultMeta.id, + }) + ); const conditionallyLinkedArticle = (children: React.ReactNode) => { return shouldLinkToDetailPage ? ( diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/utils/encode_path_params/index.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/utils/encode_path_params/index.test.ts new file mode 100644 index 00000000000000..772105c6a12355 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/utils/encode_path_params/index.test.ts @@ -0,0 +1,20 @@ +/* + * 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 { encodePathParams } from './'; + +describe('encodePathParams', () => { + it('encodeURIComponent()s all object values', () => { + const params = { + someValue: 'hello world???', + anotherValue: 'test!@#$%^&*[]/|;:"<>~`', + }; + expect(encodePathParams(params)).toEqual({ + someValue: 'hello%20world%3F%3F%3F', + anotherValue: 'test!%40%23%24%25%5E%26*%5B%5D%2F%7C%3B%3A%22%3C%3E~%60', + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/utils/encode_path_params/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/utils/encode_path_params/index.ts new file mode 100644 index 00000000000000..a17e3b11cbd152 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/utils/encode_path_params/index.ts @@ -0,0 +1,15 @@ +/* + * 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. + */ + +export const encodePathParams = (pathParams: Record) => { + const encodedParams: Record = {}; + + Object.entries(pathParams).map(([key, value]) => { + encodedParams[key] = encodeURIComponent(value); + }); + + return encodedParams; +}; From 5a2d9a64fdc22ff30fa35cd6a47e73ae22f4f30b Mon Sep 17 00:00:00 2001 From: Constance Chen Date: Fri, 29 Jan 2021 15:28:12 -0800 Subject: [PATCH 2/8] Add useDecodedParams helper + update components that need it - Documents titles & Analytics queries --- .../analytics/views/query_detail.tsx | 7 ++++--- .../components/documents/document_detail.tsx | 8 ++++---- .../utils/encode_path_params/index.test.ts | 18 +++++++++++++++++- .../utils/encode_path_params/index.ts | 13 +++++++++++++ 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/query_detail.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/query_detail.tsx index d5d864f35f6819..0ec81f5caa9357 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/query_detail.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/query_detail.tsx @@ -5,7 +5,6 @@ */ import React from 'react'; -import { useParams } from 'react-router-dom'; import { useValues } from 'kea'; import { i18n } from '@kbn/i18n'; @@ -13,6 +12,7 @@ import { EuiSpacer } from '@elastic/eui'; import { SetAppSearchChrome as SetPageChrome } from '../../../../shared/kibana_chrome'; import { BreadcrumbTrail } from '../../../../shared/kibana_chrome/generate_breadcrumbs'; +import { useDecodedParams } from '../../../utils/encode_path_params'; import { AnalyticsLayout } from '../analytics_layout'; import { AnalyticsSection, QueryClicksTable } from '../components'; @@ -27,14 +27,15 @@ interface Props { breadcrumbs: BreadcrumbTrail; } export const QueryDetail: React.FC = ({ breadcrumbs }) => { - const { query } = useParams() as { query: string }; + const { query } = useDecodedParams(); + const queryTitle = query === '""' ? query : `"${query}"`; const { totalQueriesForQuery, queriesPerDayForQuery, startDate, topClicksForQuery } = useValues( AnalyticsLogic ); return ( - + = ({ engineBreadcrumb }) => { const { deleteDocument, getDocumentDetails, setFields } = useActions(DocumentDetailLogic); const { documentId } = useParams() as { documentId: string }; + const { documentId: documentTitle } = useDecodedParams(); useEffect(() => { getDocumentDetails(documentId); @@ -74,13 +76,11 @@ export const DocumentDetail: React.FC = ({ engineBreadcrumb }) => { return ( <> - + -

{DOCUMENT_DETAIL_TITLE(decodeURIComponent(documentId))}

+

{DOCUMENT_DETAIL_TITLE(documentTitle)}

diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/utils/encode_path_params/index.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/utils/encode_path_params/index.test.ts index 772105c6a12355..bff318a0728275 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/utils/encode_path_params/index.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/utils/encode_path_params/index.test.ts @@ -4,7 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { encodePathParams } from './'; +import '../../../__mocks__/react_router_history.mock'; +import { useParams } from 'react-router-dom'; + +import { encodePathParams, useDecodedParams } from './'; describe('encodePathParams', () => { it('encodeURIComponent()s all object values', () => { @@ -18,3 +21,16 @@ describe('encodePathParams', () => { }); }); }); + +describe('useDecodedParams', () => { + it('decodeURIComponent()s all object values from useParams()', () => { + (useParams as jest.Mock).mockReturnValue({ + someValue: 'hello%20world%3F%3F%3F', + anotherValue: 'test!%40%23%24%25%5E%26*%5B%5D%2F%7C%3B%3A%22%3C%3E~%60', + }); + expect(useDecodedParams()).toEqual({ + someValue: 'hello world???', + anotherValue: 'test!@#$%^&*[]/|;:"<>~`', + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/utils/encode_path_params/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/utils/encode_path_params/index.ts index a17e3b11cbd152..7caec1e259df42 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/utils/encode_path_params/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/utils/encode_path_params/index.ts @@ -4,6 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ +import { useParams } from 'react-router-dom'; + export const encodePathParams = (pathParams: Record) => { const encodedParams: Record = {}; @@ -13,3 +15,14 @@ export const encodePathParams = (pathParams: Record) => return encodedParams; }; + +export const useDecodedParams = () => { + const decodedParams: Record = {}; + + const params = useParams(); + Object.entries(params).map(([key, value]) => { + decodedParams[key] = decodeURIComponent(value as string); + }); + + return decodedParams; +}; From c0ad74e6236ef12dda603a8201f37a76040cb86b Mon Sep 17 00:00:00 2001 From: Constance Chen Date: Fri, 29 Jan 2021 16:18:09 -0800 Subject: [PATCH 3/8] [Misc] Change popout icon to eye - Feedback from Davey - the pages don't open in a new window, so shouldn't use the popout icon - Not strictly related but since we're touching these links anyway, I'm shoving it in (sorry) --- .../analytics/components/analytics_tables/shared_columns.tsx | 2 +- .../public/applications/app_search/components/result/result.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/shared_columns.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/shared_columns.tsx index 16743405e0b5e1..8546ee428b6815 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/shared_columns.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/shared_columns.tsx @@ -56,7 +56,7 @@ export const ACTIONS_COLUMN = { { defaultMessage: 'View query analytics' } ), type: 'icon', - icon: 'popout', + icon: 'eye', color: 'primary', onClick: (item: Query | RecentQuery) => { const { navigateToUrl } = KibanaLogic.values; 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 3837e65b3a376c..c11bc5e0241ccb 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 @@ -139,7 +139,7 @@ export const Result: React.FC = ({ { defaultMessage: 'Visit document details' } )} > - +
)} From 12e4db95d8277c073dcdc1c22fc6f5e9b2a34069 Mon Sep 17 00:00:00 2001 From: Constance Chen Date: Mon, 1 Feb 2021 14:51:47 -0800 Subject: [PATCH 4/8] Remove document detail decode test - now handled/tested by useDecodedParams helper --- .../components/documents/document_detail.test.tsx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail.test.tsx index 607b2ce3c0d78f..0d007afbd04993 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail.test.tsx @@ -104,10 +104,4 @@ describe('DocumentDetail', () => { expect(actions.deleteDocument).toHaveBeenCalledWith('1'); }); - - it('correctly decodes document IDs', () => { - (useParams as jest.Mock).mockReturnValueOnce({ documentId: 'hello%20world%20%26%3F!' }); - const wrapper = shallow(); - expect(wrapper.find('h1').text()).toEqual('Document: hello world &?!'); - }); }); From 68a30579737ec24fa5c69da44e0c0f1b00b52396 Mon Sep 17 00:00:00 2001 From: Constance Chen Date: Mon, 1 Feb 2021 16:00:27 -0800 Subject: [PATCH 5/8] Add new generateEncodedPath helper - Should be used in place of generatePath --- .../utils/encode_path_params/index.test.ts | 15 ++++++++++++++- .../app_search/utils/encode_path_params/index.ts | 14 ++++++++++---- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/utils/encode_path_params/index.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/utils/encode_path_params/index.test.ts index bff318a0728275..f311909bdf5bec 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/utils/encode_path_params/index.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/utils/encode_path_params/index.test.ts @@ -7,7 +7,7 @@ import '../../../__mocks__/react_router_history.mock'; import { useParams } from 'react-router-dom'; -import { encodePathParams, useDecodedParams } from './'; +import { encodePathParams, generateEncodedPath, useDecodedParams } from './'; describe('encodePathParams', () => { it('encodeURIComponent()s all object values', () => { @@ -22,6 +22,19 @@ describe('encodePathParams', () => { }); }); +describe('generateEncodedPath', () => { + it('generates a react router path with encoded path parameters', () => { + expect( + generateEncodedPath('/values/:someValue/:anotherValue/new', { + someValue: 'hello world???', + anotherValue: 'test!@#$%^&*[]/|;:"<>~`', + }) + ).toEqual( + '/values/hello%20world%3F%3F%3F/test!%40%23%24%25%5E%26*%5B%5D%2F%7C%3B%3A%22%3C%3E~%60/new' + ); + }); +}); + describe('useDecodedParams', () => { it('decodeURIComponent()s all object values from useParams()', () => { (useParams as jest.Mock).mockReturnValue({ diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/utils/encode_path_params/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/utils/encode_path_params/index.ts index 7caec1e259df42..c8934ba47fe454 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/utils/encode_path_params/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/utils/encode_path_params/index.ts @@ -4,10 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { useParams } from 'react-router-dom'; +import { generatePath, useParams } from 'react-router-dom'; -export const encodePathParams = (pathParams: Record) => { - const encodedParams: Record = {}; +type PathParams = Record; + +export const encodePathParams = (pathParams: PathParams) => { + const encodedParams: PathParams = {}; Object.entries(pathParams).map(([key, value]) => { encodedParams[key] = encodeURIComponent(value); @@ -16,8 +18,12 @@ export const encodePathParams = (pathParams: Record) => return encodedParams; }; +export const generateEncodedPath = (path: string, pathParams: PathParams) => { + return generatePath(path, encodePathParams(pathParams)); +}; + export const useDecodedParams = () => { - const decodedParams: Record = {}; + const decodedParams: PathParams = {}; const params = useParams(); Object.entries(params).map(([key, value]) => { From a72aef29c266aa473c3654e2db0fe565bb23efde Mon Sep 17 00:00:00 2001 From: Constance Chen Date: Mon, 1 Feb 2021 16:07:18 -0800 Subject: [PATCH 6/8] Update all instances of generatePath to generateEncodedPath for consistency across the App Search codebase --- .../app_search/__mocks__/engine_logic.mock.ts | 4 ++-- .../app_search/components/engine/utils.ts | 6 ++---- .../components/engines/engines_table.tsx | 4 ++-- .../app_search/components/result/result.tsx | 14 +++++--------- 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/__mocks__/engine_logic.mock.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/__mocks__/engine_logic.mock.ts index 6326a41c1d2ca4..edc87d7025c5d0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/__mocks__/engine_logic.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/__mocks__/engine_logic.mock.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { generatePath } from 'react-router-dom'; +import { generateEncodedPath } from '../utils/encode_path_params'; export const mockEngineValues = { engineName: 'some-engine', @@ -12,7 +12,7 @@ export const mockEngineValues = { }; export const mockGenerateEnginePath = jest.fn((path, pathParams = {}) => - generatePath(path, { engineName: mockEngineValues.engineName, ...pathParams }) + generateEncodedPath(path, { engineName: mockEngineValues.engineName, ...pathParams }) ); jest.mock('../components/engine', () => ({ diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/utils.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/utils.ts index 4fd9d4cef8fa41..8e197eb402ea7b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/utils.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/utils.ts @@ -4,9 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { generatePath } from 'react-router-dom'; - -import { encodePathParams } from '../../utils/encode_path_params'; +import { generateEncodedPath } from '../../utils/encode_path_params'; import { EngineLogic } from './'; @@ -15,5 +13,5 @@ import { EngineLogic } from './'; */ export const generateEnginePath = (path: string, pathParams: object = {}) => { const { engineName } = EngineLogic.values; - return generatePath(path, encodePathParams({ engineName, ...pathParams })); + return generateEncodedPath(path, { engineName, ...pathParams }); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.tsx index a9455b4a2306ab..34bf0fe1b3a04e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.tsx @@ -5,7 +5,6 @@ */ import React from 'react'; -import { generatePath } from 'react-router-dom'; import { useActions } from 'kea'; import { EuiBasicTable, EuiBasicTableColumn } from '@elastic/eui'; import { FormattedMessage, FormattedDate, FormattedNumber } from '@kbn/i18n/react'; @@ -13,6 +12,7 @@ import { i18n } from '@kbn/i18n'; import { TelemetryLogic } from '../../../shared/telemetry'; import { EuiLinkTo } from '../../../shared/react_router_helpers'; +import { generateEncodedPath } from '../../utils/encode_path_params'; import { ENGINE_PATH } from '../../routes'; import { ENGINES_PAGE_SIZE } from '../../../../../common/constants'; @@ -41,7 +41,7 @@ export const EnginesTable: React.FC = ({ const { sendAppSearchTelemetry } = useActions(TelemetryLogic); const engineLinkProps = (engineName: string) => ({ - to: generatePath(ENGINE_PATH, { engineName }), + to: generateEncodedPath(ENGINE_PATH, { engineName }), onClick: () => sendAppSearchTelemetry({ action: 'clicked', 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 c11bc5e0241ccb..ff8b373f1bee33 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 @@ -5,7 +5,6 @@ */ import React, { useState, useMemo } from 'react'; -import { generatePath } from 'react-router-dom'; import classNames from 'classnames'; import './result.scss'; @@ -14,7 +13,7 @@ import { EuiPanel, EuiIcon } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ReactRouterHelper } from '../../../shared/react_router_helpers/eui_components'; -import { encodePathParams } from '../../utils/encode_path_params'; +import { generateEncodedPath } from '../../utils/encode_path_params'; import { ENGINE_DOCUMENT_DETAIL_PATH } from '../../routes'; import { Schema } from '../../../shared/types'; @@ -53,13 +52,10 @@ export const Result: React.FC = ({ if (schemaForTypeHighlights) return schemaForTypeHighlights[fieldName]; }; - const documentLink = generatePath( - ENGINE_DOCUMENT_DETAIL_PATH, - encodePathParams({ - engineName: resultMeta.engine, - documentId: resultMeta.id, - }) - ); + const documentLink = generateEncodedPath(ENGINE_DOCUMENT_DETAIL_PATH, { + engineName: resultMeta.engine, + documentId: resultMeta.id, + }); const conditionallyLinkedArticle = (children: React.ReactNode) => { return shouldLinkToDetailPage ? ( From 9dd3fdfb536c1d1744799ec99f4a774b09fad005 Mon Sep 17 00:00:00 2001 From: Constance Chen Date: Mon, 1 Feb 2021 16:08:08 -0800 Subject: [PATCH 7/8] Fix failing tests due to extra encodeURI() done by generatePath --- .../__mocks__/react_router_history.mock.ts | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/react_router_history.mock.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/react_router_history.mock.ts index 1516aa9096eca0..d3c11d33fdbf7e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/react_router_history.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/react_router_history.mock.ts @@ -24,12 +24,20 @@ export const mockLocation = { state: {}, }; -jest.mock('react-router-dom', () => ({ - ...(jest.requireActual('react-router-dom') as object), - useHistory: jest.fn(() => mockHistory), - useLocation: jest.fn(() => mockLocation), - useParams: jest.fn(() => ({})), -})); +jest.mock('react-router-dom', () => { + const originalModule = jest.requireActual('react-router-dom'); + return { + ...originalModule, + useHistory: jest.fn(() => mockHistory), + useLocation: jest.fn(() => mockLocation), + useParams: jest.fn(() => ({})), + // Note: RR's generatePath() opinionatedly encodeURI()s paths (although this doesn't actually + // show up/affect the final browser URL). Since we already have a generateEncodedPath helper & + // RR is removing this behavior in history 5.0+, I'm mocking tests to remove the extra encoding + // for now to make reading generateEncodedPath URLs a little less of a pain + generatePath: jest.fn((path, params) => decodeURI(originalModule.generatePath(path, params))), + }; +}); /** * For example usage, @see public/applications/shared/react_router_helpers/eui_link.test.tsx From b4b4b6aec73b200022d294b7b49a7c0a3c046a3e Mon Sep 17 00:00:00 2001 From: Constance Chen Date: Mon, 1 Feb 2021 16:10:02 -0800 Subject: [PATCH 8/8] Add missing branch test for analytics query titles --- .../components/analytics/views/query_detail.test.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/query_detail.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/query_detail.test.tsx index 7705d342ecdce5..42f13a0631a0aa 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/query_detail.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/query_detail.test.tsx @@ -13,6 +13,7 @@ import { shallow } from 'enzyme'; import { SetAppSearchChrome as SetPageChrome } from '../../../../shared/kibana_chrome'; +import { AnalyticsLayout } from '../analytics_layout'; import { AnalyticsCards, AnalyticsChart, QueryClicksTable } from '../components'; import { QueryDetail } from './'; @@ -20,7 +21,7 @@ describe('QueryDetail', () => { const mockBreadcrumbs = ['Engines', 'some-engine', 'Analytics']; beforeEach(() => { - (useParams as jest.Mock).mockReturnValueOnce({ query: 'some-query' }); + (useParams as jest.Mock).mockReturnValue({ query: 'some-query' }); setMockValues({ totalQueriesForQuery: 100, @@ -31,6 +32,7 @@ describe('QueryDetail', () => { it('renders', () => { const wrapper = shallow(); + expect(wrapper.find(AnalyticsLayout).prop('title')).toEqual('"some-query"'); expect(wrapper.find(SetPageChrome).prop('trail')).toEqual([ 'Engines', 'some-engine', @@ -43,4 +45,11 @@ describe('QueryDetail', () => { expect(wrapper.find(AnalyticsChart)).toHaveLength(1); expect(wrapper.find(QueryClicksTable)).toHaveLength(1); }); + + it('renders empty "" search titles correctly', () => { + (useParams as jest.Mock).mockReturnValue({ query: '""' }); + const wrapper = shallow(); + + expect(wrapper.find(AnalyticsLayout).prop('title')).toEqual('""'); + }); });