From 500ac52ff5368e61a0b9353324147c8af8b9eb18 Mon Sep 17 00:00:00 2001
From: Byron Hulcher
Date: Thu, 11 Mar 2021 11:48:39 -0500
Subject: [PATCH 01/11] Added new onboarding complete route for App Search
---
.../server/routes/app_search/index.ts | 2 +
.../routes/app_search/onboarding.test.ts | 41 +++++++++++++++++++
.../server/routes/app_search/onboarding.ts | 29 +++++++++++++
3 files changed, 72 insertions(+)
create mode 100644 x-pack/plugins/enterprise_search/server/routes/app_search/onboarding.test.ts
create mode 100644 x-pack/plugins/enterprise_search/server/routes/app_search/onboarding.ts
diff --git a/x-pack/plugins/enterprise_search/server/routes/app_search/index.ts b/x-pack/plugins/enterprise_search/server/routes/app_search/index.ts
index 1bd88c111f79f..3c8501ec15b3d 100644
--- a/x-pack/plugins/enterprise_search/server/routes/app_search/index.ts
+++ b/x-pack/plugins/enterprise_search/server/routes/app_search/index.ts
@@ -12,6 +12,7 @@ import { registerCredentialsRoutes } from './credentials';
import { registerCurationsRoutes } from './curations';
import { registerDocumentsRoutes, registerDocumentRoutes } from './documents';
import { registerEnginesRoutes } from './engines';
+import { registerOnboardingRoutes } from './onboarding';
import { registerResultSettingsRoutes } from './result_settings';
import { registerRoleMappingsRoutes } from './role_mappings';
import { registerSearchSettingsRoutes } from './search_settings';
@@ -28,4 +29,5 @@ export const registerAppSearchRoutes = (dependencies: RouteDependencies) => {
registerSearchSettingsRoutes(dependencies);
registerRoleMappingsRoutes(dependencies);
registerResultSettingsRoutes(dependencies);
+ registerOnboardingRoutes(dependencies);
};
diff --git a/x-pack/plugins/enterprise_search/server/routes/app_search/onboarding.test.ts b/x-pack/plugins/enterprise_search/server/routes/app_search/onboarding.test.ts
new file mode 100644
index 0000000000000..c26f8dbaf5213
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/server/routes/app_search/onboarding.test.ts
@@ -0,0 +1,41 @@
+/*
+ * 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 { MockRouter, mockRequestHandler, mockDependencies } from '../../__mocks__';
+
+import { registerOnboardingRoutes } from './onboarding';
+
+describe('engine routes', () => {
+ describe('POST /api/app_search/onboarding_complete', () => {
+ let mockRouter: MockRouter;
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+ mockRouter = new MockRouter({
+ method: 'post',
+ path: '/api/app_search/onboarding_complete',
+ });
+
+ registerOnboardingRoutes({
+ ...mockDependencies,
+ router: mockRouter.router,
+ });
+ });
+
+ it('creates a request handler', () => {
+ mockRouter.callRoute({ body: {} });
+ expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({
+ path: '/as/onboarding/complete',
+ });
+ });
+
+ it('validates seed_sample_engine ', () => {
+ const request = { body: { seed_sample_engine: true } };
+ mockRouter.shouldValidate(request);
+ });
+ });
+});
diff --git a/x-pack/plugins/enterprise_search/server/routes/app_search/onboarding.ts b/x-pack/plugins/enterprise_search/server/routes/app_search/onboarding.ts
new file mode 100644
index 0000000000000..9a46c75555969
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/server/routes/app_search/onboarding.ts
@@ -0,0 +1,29 @@
+/*
+ * 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 { schema } from '@kbn/config-schema';
+
+import { RouteDependencies } from '../../plugin';
+
+export function registerOnboardingRoutes({
+ router,
+ enterpriseSearchRequestHandler,
+}: RouteDependencies) {
+ router.post(
+ {
+ path: '/api/app_search/onboarding_complete',
+ validate: {
+ body: schema.object({
+ seed_sample_engine: schema.maybe(schema.boolean()),
+ }),
+ },
+ },
+ enterpriseSearchRequestHandler.createRequest({
+ path: '/as/onboarding/complete',
+ })
+ );
+}
From 1cd26f1b6eda83f1b14ee51990f641677fcc66bc Mon Sep 17 00:00:00 2001
From: Byron Hulcher
Date: Wed, 17 Mar 2021 14:30:29 -0400
Subject: [PATCH 02/11] Allow responses without JSON bodies in Enterprise
Search
---
.../enterprise_search_request_handler.test.ts | 18 ++++++++++--
.../lib/enterprise_search_request_handler.ts | 28 +++++++++++++------
2 files changed, 35 insertions(+), 11 deletions(-)
diff --git a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.test.ts b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.test.ts
index d6a891e3f6241..f4b291bea1d12 100644
--- a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.test.ts
+++ b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.test.ts
@@ -198,6 +198,18 @@ describe('EnterpriseSearchRequestHandler', () => {
});
});
});
+
+ it('works if resposne contains no json data', async () => {
+ EnterpriseSearchAPI.mockReturn();
+
+ const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/prep' });
+ await makeAPICall(requestHandler);
+
+ expect(responseMock.custom).toHaveBeenCalledWith({
+ statusCode: 200,
+ headers: mockExpectedResponseHeaders,
+ });
+ });
});
describe('error responses', () => {
@@ -456,10 +468,12 @@ const EnterpriseSearchAPI = {
...expectedParams,
});
},
- mockReturn(response: object, options?: any) {
+ mockReturn(response?: object, options?: any) {
fetchMock.mockImplementation(() => {
const headers = Object.assign({}, mockExpectedResponseHeaders, options?.headers);
- return Promise.resolve(new Response(JSON.stringify(response), { ...options, headers }));
+ return Promise.resolve(
+ new Response(response ? JSON.stringify(response) : undefined, { ...options, headers })
+ );
});
},
mockReturnError() {
diff --git a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.ts b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.ts
index fb525740dd55b..e5394fd580efc 100644
--- a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.ts
+++ b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.ts
@@ -113,22 +113,32 @@ export class EnterpriseSearchRequestHandler {
}
// Check returned data
- const json = await apiResponse.json();
- if (!hasValidData(json)) {
- return this.handleInvalidDataError(response, url, json);
- }
+ let responseBody;
- // Intercept data that is meant for the server side session
- const { _sessionData, ...responseJson } = json;
- if (_sessionData) {
- this.setSessionData(_sessionData);
+ try {
+ const json = await apiResponse.json();
+
+ if (!hasValidData(json)) {
+ return this.handleInvalidDataError(response, url, json);
+ }
+
+ // Intercept data that is meant for the server side session
+ const { _sessionData, ...responseJson } = json;
+ if (_sessionData) {
+ this.setSessionData(_sessionData);
+ responseBody = responseJson;
+ } else {
+ responseBody = json;
+ }
+ } catch (e) {
+ responseBody = undefined;
}
// Pass successful responses back to the front-end
return response.custom({
statusCode: status,
headers: this.headers,
- body: _sessionData ? responseJson : json,
+ body: responseBody,
});
} catch (e) {
// Catch connection/auth errors
From 0e5d0750093ca1724b6683e635ddc7f357b906bd Mon Sep 17 00:00:00 2001
From: Byron Hulcher
Date: Thu, 11 Mar 2021 11:50:15 -0500
Subject: [PATCH 03/11] New SampleEngineCreationCtaLogic
---
.../sample_engine_creation_cta_logic.test.ts | 100 ++++++++++++++++++
.../sample_engine_creation_cta_logic.ts | 70 ++++++++++++
2 files changed, 170 insertions(+)
create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta_logic.test.ts
create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta_logic.ts
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta_logic.test.ts
new file mode 100644
index 0000000000000..5cb58aa1a62e4
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta_logic.test.ts
@@ -0,0 +1,100 @@
+/*
+ * 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,
+ mockHttpValues,
+ mockKibanaValues,
+ mockFlashMessageHelpers,
+} from '../../../__mocks__';
+
+import { nextTick } from '@kbn/test/jest';
+
+import { SampleEngineCreationCtaLogic } from './sample_engine_creation_cta_logic';
+
+describe('SampleEngineCreationCtaLogic', () => {
+ const { mount } = new LogicMounter(SampleEngineCreationCtaLogic);
+ const { http } = mockHttpValues;
+ const { navigateToUrl } = mockKibanaValues;
+ const { setQueuedSuccessMessage, flashAPIErrors } = mockFlashMessageHelpers;
+
+ const DEFAULT_VALUES = {
+ isLoading: false,
+ };
+
+ it('has expected default values', () => {
+ mount();
+ expect(SampleEngineCreationCtaLogic.values).toEqual(DEFAULT_VALUES);
+ });
+
+ describe('actions', () => {
+ it('setIsLoading sets isLoading', () => {
+ jest.clearAllMocks();
+ mount();
+
+ SampleEngineCreationCtaLogic.actions.setIsLoading(true);
+
+ expect(SampleEngineCreationCtaLogic.values.isLoading).toEqual(true);
+ });
+ });
+
+ describe('listeners', () => {
+ describe('createSampleEngine', () => {
+ beforeAll(() => {
+ mount();
+ });
+
+ afterAll(() => {
+ jest.clearAllMocks();
+ });
+
+ it('POSTS to /api/app_search/engines', () => {
+ const body = JSON.stringify({
+ seed_sample_engine: true,
+ });
+ SampleEngineCreationCtaLogic.actions.createSampleEngine();
+ expect(http.post).toHaveBeenCalledWith('/api/app_search/onboarding_complete', { body });
+ });
+
+ it('calls onSampleEngineCreationSuccess on valid submission', async () => {
+ jest.spyOn(SampleEngineCreationCtaLogic.actions, 'onSampleEngineCreationSuccess');
+ http.post.mockReturnValueOnce(Promise.resolve({}));
+ SampleEngineCreationCtaLogic.actions.createSampleEngine();
+ await nextTick();
+ expect(
+ SampleEngineCreationCtaLogic.actions.onSampleEngineCreationSuccess
+ ).toHaveBeenCalledTimes(1);
+ });
+
+ it('calls flashAPIErrors on API Error', async () => {
+ http.post.mockReturnValueOnce(Promise.reject());
+ SampleEngineCreationCtaLogic.actions.createSampleEngine();
+ await nextTick();
+ expect(flashAPIErrors).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ describe('onSampleEngineCreationSuccess', () => {
+ beforeAll(() => {
+ mount();
+ SampleEngineCreationCtaLogic.actions.onSampleEngineCreationSuccess();
+ });
+
+ afterAll(() => {
+ jest.clearAllMocks();
+ });
+
+ it('should set a success message', () => {
+ expect(setQueuedSuccessMessage).toHaveBeenCalledWith('Successfully created engine.');
+ });
+
+ it('should navigate the user to the engine page', () => {
+ expect(navigateToUrl).toHaveBeenCalledWith('/engines/national-parks-demo');
+ });
+ });
+ });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta_logic.ts
new file mode 100644
index 0000000000000..b67f1b94ab3c9
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta_logic.ts
@@ -0,0 +1,70 @@
+/*
+ * 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 { generatePath } from 'react-router-dom';
+
+import { kea, MakeLogicType } from 'kea';
+
+import { flashAPIErrors, setQueuedSuccessMessage } from '../../../shared/flash_messages';
+import { HttpLogic } from '../../../shared/http';
+import { KibanaLogic } from '../../../shared/kibana';
+import { ENGINE_PATH } from '../../routes';
+import { ENGINE_CREATION_SUCCESS_MESSAGE } from '../engine_creation/constants';
+
+interface SampleEngineCreationCtaActions {
+ createSampleEngine(): void;
+ onSampleEngineCreationSuccess(): void;
+ setIsLoading(isLoading: boolean): { isLoading: boolean };
+}
+
+interface SampleEngineCreationCtaValues {
+ isLoading: boolean;
+}
+
+export const SampleEngineCreationCtaLogic = kea<
+ MakeLogicType
+>({
+ path: ['enterprise_search', 'app_search', 'sample_engine_cta_logic'],
+ actions: {
+ createSampleEngine: true,
+ onSampleEngineCreationSuccess: true,
+ setIsLoading: (isLoading) => ({ isLoading }),
+ },
+ reducers: {
+ isLoading: [
+ false,
+ {
+ createSampleEngine: () => true,
+ setIsLoading: (_, { isLoading }) => isLoading,
+ },
+ ],
+ },
+ listeners: ({ actions }) => ({
+ createSampleEngine: async () => {
+ const { http } = HttpLogic.values;
+
+ const body = JSON.stringify({ seed_sample_engine: true });
+
+ try {
+ await http.post('/api/app_search/onboarding_complete', {
+ body,
+ });
+ actions.onSampleEngineCreationSuccess();
+ } catch (e) {
+ actions.setIsLoading(false);
+ flashAPIErrors(e);
+ }
+ },
+ onSampleEngineCreationSuccess: () => {
+ const { navigateToUrl } = KibanaLogic.values;
+ const enginePath = generatePath(ENGINE_PATH, { engineName: 'national-parks-demo' });
+
+ setQueuedSuccessMessage(ENGINE_CREATION_SUCCESS_MESSAGE);
+ navigateToUrl(enginePath);
+ },
+ }),
+});
From d0877ef2b92c07084104d6c2b8b8ac05301eb559 Mon Sep 17 00:00:00 2001
From: Byron Hulcher
Date: Thu, 11 Mar 2021 11:50:44 -0500
Subject: [PATCH 04/11] New SampleEngineCreationCta component
---
.../sample_engine_creation_cta/i18n.ts | 29 ++++++++++
.../sample_engine_creation_cta/index.ts | 8 +++
.../sample_engine_creation_cta.test.tsx | 55 +++++++++++++++++++
.../sample_engine_creation_cta.tsx | 48 ++++++++++++++++
4 files changed, 140 insertions(+)
create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/i18n.ts
create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/index.ts
create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta.test.tsx
create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta.tsx
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/i18n.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/i18n.ts
new file mode 100644
index 0000000000000..229a26b0fb360
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/i18n.ts
@@ -0,0 +1,29 @@
+/*
+ * 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 { i18n } from '@kbn/i18n';
+
+export const SAMPLE_ENGINE_CREATION_CTA_TITLE = i18n.translate(
+ 'xpack.enterpriseSearch.appSearch.sampleEngineCreationCta.title',
+ {
+ defaultMessage: 'Just kicking the tires?',
+ }
+);
+
+export const SAMPLE_ENGINE_CREATION_CTA_DESCRIPTION = i18n.translate(
+ 'xpack.enterpriseSearch.appSearch.sampleEngineCreationCta.description',
+ {
+ defaultMessage: 'Test an engine with sample data.',
+ }
+);
+
+export const SAMPLE_ENGINE_CREATION_CTA_BUTTON_LABEL = i18n.translate(
+ 'xpack.enterpriseSearch.appSearch.sampleEngineCreationCta.buttonLabel',
+ {
+ defaultMessage: 'Try a sample engine',
+ }
+);
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/index.ts
new file mode 100644
index 0000000000000..fa11abd19a2db
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/index.ts
@@ -0,0 +1,8 @@
+/*
+ * 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 { SampleEngineCreationCta } from './sample_engine_creation_cta';
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta.test.tsx
new file mode 100644
index 0000000000000..e831b9df7ad7e
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta.test.tsx
@@ -0,0 +1,55 @@
+/*
+ * 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 '../../../__mocks__/enterprise_search_url.mock';
+import { mountWithIntl, setMockActions, setMockValues } from '../../../__mocks__';
+
+import React from 'react';
+
+import { EuiButton } from '@elastic/eui';
+
+import { SampleEngineCreationCta } from './sample_engine_creation_cta';
+
+describe('SampleEngineCTA', () => {
+ describe('CTA button', () => {
+ const MOCK_VALUES = {
+ isLoading: false,
+ };
+
+ const MOCK_ACTIONS = {
+ createSampleEngine: jest.fn(),
+ };
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+ setMockActions(MOCK_ACTIONS);
+ setMockValues(MOCK_VALUES);
+ });
+
+ it('calls createSampleEngine on click', () => {
+ const wrapper = mountWithIntl();
+ const ctaButton = wrapper.find(EuiButton);
+
+ expect(ctaButton.props().onClick).toEqual(MOCK_ACTIONS.createSampleEngine);
+ });
+
+ it('by default enabled', () => {
+ const wrapper = mountWithIntl();
+ const ctaButton = wrapper.find(EuiButton);
+
+ expect(ctaButton.props().isLoading).toEqual(false);
+ });
+
+ it('disabled while loading', () => {
+ setMockValues({ ...MOCK_VALUES, isLoading: true });
+ const wrapper = mountWithIntl();
+ const ctaButton = wrapper.find(EuiButton);
+
+ expect(ctaButton.props().isLoading).toEqual(true);
+ });
+ });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta.tsx
new file mode 100644
index 0000000000000..4b5cf381157f2
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta.tsx
@@ -0,0 +1,48 @@
+/*
+ * 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 { useActions, useValues } from 'kea';
+
+import { EuiPanel, EuiFlexGroup, EuiFlexItem, EuiTitle, EuiText, EuiButton } from '@elastic/eui';
+
+import {
+ SAMPLE_ENGINE_CREATION_CTA_TITLE,
+ SAMPLE_ENGINE_CREATION_CTA_DESCRIPTION,
+ SAMPLE_ENGINE_CREATION_CTA_BUTTON_LABEL,
+} from './i18n';
+import { SampleEngineCreationCtaLogic } from './sample_engine_creation_cta_logic';
+
+export const SampleEngineCreationCta: React.FC = () => {
+ const { isLoading } = useValues(SampleEngineCreationCtaLogic);
+ const { createSampleEngine } = useActions(SampleEngineCreationCtaLogic);
+
+ return (
+
+
+
+
+ {SAMPLE_ENGINE_CREATION_CTA_TITLE}
+
+
+ {SAMPLE_ENGINE_CREATION_CTA_DESCRIPTION}
+
+
+
+
+ {SAMPLE_ENGINE_CREATION_CTA_BUTTON_LABEL}
+
+
+
+
+ );
+};
From 7924d2266c0a26fe955911ecedf62b9f15fa97b2 Mon Sep 17 00:00:00 2001
From: Byron Hulcher
Date: Mon, 15 Mar 2021 18:04:01 -0400
Subject: [PATCH 05/11] Add SampleEngineCreationCTA to engines EmptyState
---
.../engines/components/empty_state.test.tsx | 6 +++
.../engines/components/empty_state.tsx | 40 +++++++++++--------
2 files changed, 29 insertions(+), 17 deletions(-)
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.test.tsx
index 14772375c9bd4..066c57c2f04dd 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.test.tsx
@@ -14,6 +14,8 @@ import { shallow, ShallowWrapper } from 'enzyme';
import { EuiEmptyPrompt } from '@elastic/eui';
+import { SampleEngineCreationCta } from '../../sample_engine_creation_cta/sample_engine_creation_cta';
+
import { EmptyState } from './';
describe('EmptyState', () => {
@@ -42,5 +44,9 @@ describe('EmptyState', () => {
it('sends a user to engine creation', () => {
expect(button.prop('to')).toEqual('/engine_creation');
});
+
+ it('contains a CTA to create a sample engine', () => {
+ expect(prompt.find(SampleEngineCreationCta)).toHaveLength(1);
+ });
});
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.tsx
index fc77e2f2511e0..7edc06b1cc3df 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.tsx
@@ -9,7 +9,7 @@ import React from 'react';
import { useActions } from 'kea';
-import { EuiPageContent, EuiEmptyPrompt } from '@elastic/eui';
+import { EuiPageContent, EuiEmptyPrompt, EuiSpacer } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { SetAppSearchChrome as SetPageChrome } from '../../../../shared/kibana_chrome';
@@ -17,6 +17,8 @@ import { EuiButtonTo } from '../../../../shared/react_router_helpers';
import { TelemetryLogic } from '../../../../shared/telemetry';
import { ENGINE_CREATION_PATH } from '../../../routes';
+import { SampleEngineCreationCta } from '../../sample_engine_creation_cta/sample_engine_creation_cta';
+
import { EnginesOverviewHeader } from './header';
import './empty_state.scss';
@@ -50,22 +52,26 @@ export const EmptyState: React.FC = () => {
}
actions={
-
- sendAppSearchTelemetry({
- action: 'clicked',
- metric: 'create_first_engine_button',
- })
- }
- >
-
-
+ <>
+
+ sendAppSearchTelemetry({
+ action: 'clicked',
+ metric: 'create_first_engine_button',
+ })
+ }
+ >
+
+
+
+
+ >
}
/>
From 01a6c8dc2b4109ef0dca85b366632b6915592e31 Mon Sep 17 00:00:00 2001
From: Byron Hulcher
Date: Wed, 24 Mar 2021 11:02:35 -0400
Subject: [PATCH 06/11] Improve SampleEngineCreationCta
---
.../sample_engine_creation_cta.test.tsx | 14 ++++++++------
.../sample_engine_creation_cta.tsx | 8 ++------
2 files changed, 10 insertions(+), 12 deletions(-)
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta.test.tsx
index e831b9df7ad7e..992afe4356a07 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta.test.tsx
@@ -6,10 +6,12 @@
*/
import '../../../__mocks__/enterprise_search_url.mock';
-import { mountWithIntl, setMockActions, setMockValues } from '../../../__mocks__';
+import { setMockActions, setMockValues } from '../../../__mocks__';
import React from 'react';
+import { shallow } from 'enzyme';
+
import { EuiButton } from '@elastic/eui';
import { SampleEngineCreationCta } from './sample_engine_creation_cta';
@@ -31,22 +33,22 @@ describe('SampleEngineCTA', () => {
});
it('calls createSampleEngine on click', () => {
- const wrapper = mountWithIntl();
+ const wrapper = shallow();
const ctaButton = wrapper.find(EuiButton);
expect(ctaButton.props().onClick).toEqual(MOCK_ACTIONS.createSampleEngine);
});
- it('by default enabled', () => {
- const wrapper = mountWithIntl();
+ it('is enabled by default', () => {
+ const wrapper = shallow();
const ctaButton = wrapper.find(EuiButton);
expect(ctaButton.props().isLoading).toEqual(false);
});
- it('disabled while loading', () => {
+ it('is disabled while loading', () => {
setMockValues({ ...MOCK_VALUES, isLoading: true });
- const wrapper = mountWithIntl();
+ const wrapper = shallow();
const ctaButton = wrapper.find(EuiButton);
expect(ctaButton.props().isLoading).toEqual(true);
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta.tsx
index 4b5cf381157f2..8de6b6030ef66 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta.tsx
@@ -23,7 +23,7 @@ export const SampleEngineCreationCta: React.FC = () => {
const { createSampleEngine } = useActions(SampleEngineCreationCtaLogic);
return (
-
+
@@ -34,11 +34,7 @@ export const SampleEngineCreationCta: React.FC = () => {
-
+
{SAMPLE_ENGINE_CREATION_CTA_BUTTON_LABEL}
From 0b052db8dc6f0a75c20d372c218ac7e703c9c028 Mon Sep 17 00:00:00 2001
From: Byron Hulcher
Date: Wed, 24 Mar 2021 11:03:33 -0400
Subject: [PATCH 07/11] Fix spelling error in Enterprise Search request handler
test
---
.../server/lib/enterprise_search_request_handler.test.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.test.ts b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.test.ts
index f4b291bea1d12..abe5272fe3263 100644
--- a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.test.ts
+++ b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.test.ts
@@ -199,7 +199,7 @@ describe('EnterpriseSearchRequestHandler', () => {
});
});
- it('works if resposne contains no json data', async () => {
+ it('works if response contains no json data', async () => {
EnterpriseSearchAPI.mockReturn();
const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/prep' });
From 7aac42ca9b769bf31626109c6c4d089466890b4e Mon Sep 17 00:00:00 2001
From: Byron Hulcher
Date: Wed, 24 Mar 2021 11:19:16 -0400
Subject: [PATCH 08/11] Improve SampleEngineCreationCtaLogic
---
.../sample_engine_creation_cta_logic.test.ts | 54 ++++++++-----------
.../sample_engine_creation_cta_logic.ts | 8 +--
2 files changed, 28 insertions(+), 34 deletions(-)
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta_logic.test.ts
index 5cb58aa1a62e4..740c4df697d68 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta_logic.test.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta_logic.test.ts
@@ -26,75 +26,67 @@ describe('SampleEngineCreationCtaLogic', () => {
isLoading: false,
};
- it('has expected default values', () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
mount();
+ });
+
+ it('has expected default values', () => {
expect(SampleEngineCreationCtaLogic.values).toEqual(DEFAULT_VALUES);
});
describe('actions', () => {
- it('setIsLoading sets isLoading', () => {
- jest.clearAllMocks();
- mount();
+ it('onSampleEngineCreationFailure sets isLoading to false', () => {
+ mount({ isLoading: true });
- SampleEngineCreationCtaLogic.actions.setIsLoading(true);
+ SampleEngineCreationCtaLogic.actions.onSampleEngineCreationFailure();
- expect(SampleEngineCreationCtaLogic.values.isLoading).toEqual(true);
+ expect(SampleEngineCreationCtaLogic.values.isLoading).toEqual(false);
});
});
describe('listeners', () => {
describe('createSampleEngine', () => {
- beforeAll(() => {
- mount();
- });
-
- afterAll(() => {
- jest.clearAllMocks();
- });
-
it('POSTS to /api/app_search/engines', () => {
const body = JSON.stringify({
seed_sample_engine: true,
});
SampleEngineCreationCtaLogic.actions.createSampleEngine();
+
expect(http.post).toHaveBeenCalledWith('/api/app_search/onboarding_complete', { body });
});
it('calls onSampleEngineCreationSuccess on valid submission', async () => {
jest.spyOn(SampleEngineCreationCtaLogic.actions, 'onSampleEngineCreationSuccess');
http.post.mockReturnValueOnce(Promise.resolve({}));
+
SampleEngineCreationCtaLogic.actions.createSampleEngine();
await nextTick();
+
expect(
SampleEngineCreationCtaLogic.actions.onSampleEngineCreationSuccess
).toHaveBeenCalledTimes(1);
});
- it('calls flashAPIErrors on API Error', async () => {
+ it('calls onSampleEngineCreationFailure and flashAPIErrors on API Error', async () => {
+ jest.spyOn(SampleEngineCreationCtaLogic.actions, 'onSampleEngineCreationFailure');
http.post.mockReturnValueOnce(Promise.reject());
+
SampleEngineCreationCtaLogic.actions.createSampleEngine();
await nextTick();
+
expect(flashAPIErrors).toHaveBeenCalledTimes(1);
+ expect(
+ SampleEngineCreationCtaLogic.actions.onSampleEngineCreationFailure
+ ).toHaveBeenCalledTimes(1);
});
});
- describe('onSampleEngineCreationSuccess', () => {
- beforeAll(() => {
- mount();
- SampleEngineCreationCtaLogic.actions.onSampleEngineCreationSuccess();
- });
-
- afterAll(() => {
- jest.clearAllMocks();
- });
+ it('onSampleEngineCreationSuccess should set a success message and navigate the user to the engine page', () => {
+ SampleEngineCreationCtaLogic.actions.onSampleEngineCreationSuccess();
- it('should set a success message', () => {
- expect(setQueuedSuccessMessage).toHaveBeenCalledWith('Successfully created engine.');
- });
-
- it('should navigate the user to the engine page', () => {
- expect(navigateToUrl).toHaveBeenCalledWith('/engines/national-parks-demo');
- });
+ expect(setQueuedSuccessMessage).toHaveBeenCalledWith('Successfully created engine.');
+ expect(navigateToUrl).toHaveBeenCalledWith('/engines/national-parks-demo');
});
});
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta_logic.ts
index b67f1b94ab3c9..37570d4e3cfe7 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta_logic.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta_logic.ts
@@ -18,6 +18,7 @@ import { ENGINE_CREATION_SUCCESS_MESSAGE } from '../engine_creation/constants';
interface SampleEngineCreationCtaActions {
createSampleEngine(): void;
onSampleEngineCreationSuccess(): void;
+ onSampleEngineCreationFailure(): void;
setIsLoading(isLoading: boolean): { isLoading: boolean };
}
@@ -32,14 +33,15 @@ export const SampleEngineCreationCtaLogic = kea<
actions: {
createSampleEngine: true,
onSampleEngineCreationSuccess: true,
- setIsLoading: (isLoading) => ({ isLoading }),
+ onSampleEngineCreationFailure: true,
},
reducers: {
isLoading: [
false,
{
createSampleEngine: () => true,
- setIsLoading: (_, { isLoading }) => isLoading,
+ onSampleEngineCreationSuccess: () => false,
+ onSampleEngineCreationFailure: () => false,
},
],
},
@@ -55,7 +57,7 @@ export const SampleEngineCreationCtaLogic = kea<
});
actions.onSampleEngineCreationSuccess();
} catch (e) {
- actions.setIsLoading(false);
+ actions.onSampleEngineCreationFailure();
flashAPIErrors(e);
}
},
From 13c9801e98678cb29b29bc356b0b3fa1327a3a1e Mon Sep 17 00:00:00 2001
From: Byron Hulcher
Date: Mon, 29 Mar 2021 09:24:55 -0400
Subject: [PATCH 09/11] Fix types
---
.../app_search/components/engines/components/empty_state.tsx | 1 -
1 file changed, 1 deletion(-)
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.tsx
index 8fbfe783a8b7d..37c67c1f8d6f2 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.tsx
@@ -11,7 +11,6 @@ import { useValues, useActions } from 'kea';
import { EuiPageContent, EuiEmptyPrompt, EuiSpacer } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { FormattedMessage } from '@kbn/i18n/react';
import { SetAppSearchChrome as SetPageChrome } from '../../../../shared/kibana_chrome';
import { EuiButtonTo } from '../../../../shared/react_router_helpers';
From a11756516c46d4cc67f05c1873e5623eca16ade9 Mon Sep 17 00:00:00 2001
From: Byron Hulcher
Date: Mon, 29 Mar 2021 11:20:41 -0400
Subject: [PATCH 10/11] Fix tests after origin/master merge
---
.../engines/components/empty_state.test.tsx | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.test.tsx
index dd42291fd8d43..8e1488646f4d8 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.test.tsx
@@ -14,8 +14,6 @@ import { shallow, ShallowWrapper } from 'enzyme';
import { EuiEmptyPrompt } from '@elastic/eui';
-import { SampleEngineCreationCta } from '../../sample_engine_creation_cta/sample_engine_creation_cta';
-
import { EmptyState } from './';
describe('EmptyState', () => {
@@ -27,6 +25,10 @@ describe('EmptyState', () => {
wrapper = shallow();
});
+ afterAll(() => {
+ jest.clearAllMocks();
+ });
+
it('renders a prompt to create an engine', () => {
expect(wrapper.find('[data-test-subj="AdminEmptyEnginesPrompt"]')).toHaveLength(1);
});
@@ -52,18 +54,19 @@ describe('EmptyState', () => {
});
describe('when the user cannot manage/create engines', () => {
+ let wrapper: ShallowWrapper;
+
beforeAll(() => {
setMockValues({ myRole: { canManageEngines: false } });
+ wrapper = shallow();
});
- it('renders a prompt to contact the App Search admin', () => {
- const wrapper = shallow();
-
- expect(wrapper.find('[data-test-subj="NonAdminEmptyEnginesPrompt"]')).toHaveLength(1);
+ afterAll(() => {
+ jest.clearAllMocks();
});
- it('contains a CTA to create a sample engine', () => {
- expect(prompt.find(SampleEngineCreationCta)).toHaveLength(1);
+ it('renders a prompt to contact the App Search admin', () => {
+ expect(wrapper.find('[data-test-subj="NonAdminEmptyEnginesPrompt"]')).toHaveLength(1);
});
});
});
From 522a82a9e2f9b7a21b69bfe43fde97d224df743c Mon Sep 17 00:00:00 2001
From: Byron Hulcher
Date: Mon, 29 Mar 2021 11:25:07 -0400
Subject: [PATCH 11/11] Turns out I 'fixed' my tests by removing this test
---
.../components/engines/components/empty_state.test.tsx | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.test.tsx
index 8e1488646f4d8..222041c9f85a3 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.test.tsx
@@ -14,15 +14,19 @@ import { shallow, ShallowWrapper } from 'enzyme';
import { EuiEmptyPrompt } from '@elastic/eui';
+import { SampleEngineCreationCta } from '../../sample_engine_creation_cta';
+
import { EmptyState } from './';
describe('EmptyState', () => {
describe('when the user can manage/create engines', () => {
let wrapper: ShallowWrapper;
+ let prompt: ShallowWrapper;
beforeAll(() => {
setMockValues({ myRole: { canManageEngines: true } });
wrapper = shallow();
+ prompt = wrapper.find(EuiEmptyPrompt).dive();
});
afterAll(() => {
@@ -33,12 +37,14 @@ describe('EmptyState', () => {
expect(wrapper.find('[data-test-subj="AdminEmptyEnginesPrompt"]')).toHaveLength(1);
});
+ it('contains a sample engine CTA', () => {
+ expect(prompt.find(SampleEngineCreationCta)).toHaveLength(1);
+ });
+
describe('create engine button', () => {
- let prompt: ShallowWrapper;
let button: ShallowWrapper;
beforeAll(() => {
- prompt = wrapper.find(EuiEmptyPrompt).dive();
button = prompt.find('[data-test-subj="EmptyStateCreateFirstEngineCta"]');
});