-
+
{
@@ -74,7 +75,7 @@ export default function({ getService, getPageObjects }) {
await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
await PageObjects.discover.setChartInterval('Weekly');
await PageObjects.header.waitUntilLoadingHasFinished();
- const chartCanvasExist = await PageObjects.discover.chartCanvasExist();
+ const chartCanvasExist = await elasticChart.canvasExists();
expect(chartCanvasExist).to.be(true);
});
it('should visualize monthly data with different years Scaled to 30d', async () => {
@@ -84,7 +85,7 @@ export default function({ getService, getPageObjects }) {
await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
await PageObjects.discover.setChartInterval('Daily');
await PageObjects.header.waitUntilLoadingHasFinished();
- const chartCanvasExist = await PageObjects.discover.chartCanvasExist();
+ const chartCanvasExist = await elasticChart.canvasExists();
expect(chartCanvasExist).to.be(true);
});
});
diff --git a/test/functional/apps/discover/_source_filters.js b/test/functional/apps/discover/_source_filters.js
index e9cb2f3d622a2..74d0da7cdb3e7 100644
--- a/test/functional/apps/discover/_source_filters.js
+++ b/test/functional/apps/discover/_source_filters.js
@@ -49,7 +49,6 @@ export default function({ getService, getPageObjects }) {
});
it('should not get the field referer', async function() {
- //let fieldNames;
const fieldNames = await PageObjects.discover.getAllFieldNames();
expect(fieldNames).to.not.contain('referer');
const relatedContentFields = fieldNames.filter(
diff --git a/test/functional/page_objects/discover_page.js b/test/functional/page_objects/discover_page.ts
similarity index 58%
rename from test/functional/page_objects/discover_page.js
rename to test/functional/page_objects/discover_page.ts
index 46aadc63c64f1..f018a1ceda507 100644
--- a/test/functional/page_objects/discover_page.js
+++ b/test/functional/page_objects/discover_page.ts
@@ -18,40 +18,34 @@
*/
import expect from '@kbn/expect';
+import { FtrProviderContext } from '../ftr_provider_context';
-export function DiscoverPageProvider({ getService, getPageObjects }) {
+export function DiscoverPageProvider({ getService, getPageObjects }: FtrProviderContext) {
const log = getService('log');
const retry = getService('retry');
const testSubjects = getService('testSubjects');
const find = getService('find');
const flyout = getService('flyout');
- const PageObjects = getPageObjects(['header', 'common']);
+ const { header } = getPageObjects(['header']);
const browser = getService('browser');
const globalNav = getService('globalNav');
const config = getService('config');
const defaultFindTimeout = config.get('timeouts.find');
const elasticChart = getService('elasticChart');
+ const docTable = getService('docTable');
class DiscoverPage {
- async getQueryField() {
- return await find.byCssSelector("input[ng-model='state.query']");
- }
-
- async getQuerySearchButton() {
- return await find.byCssSelector("button[aria-label='Search']");
- }
-
- async getChartTimespan() {
+ public async getChartTimespan() {
const el = await find.byCssSelector('.small > label[for="dscResultsIntervalSelector"]');
return await el.getVisibleText();
}
- async saveSearch(searchName) {
+ public async saveSearch(searchName: string) {
log.debug('saveSearch');
await this.clickSaveSearchButton();
await testSubjects.setValue('savedObjectTitle', searchName);
await testSubjects.click('confirmSaveSavedObjectButton');
- await PageObjects.header.waitUntilLoadingHasFinished();
+ await header.waitUntilLoadingHasFinished();
// LeeDr - this additional checking for the saved search name was an attempt
// to cause this method to wait for the reloading of the page to complete so
// that the next action wouldn't have to retry. But it doesn't really solve
@@ -63,30 +57,29 @@ export function DiscoverPageProvider({ getService, getPageObjects }) {
});
}
- async inputSavedSearchTitle(searchName) {
+ public async inputSavedSearchTitle(searchName: string) {
await testSubjects.setValue('savedObjectTitle', searchName);
}
- async clickConfirmSavedSearch() {
+ public async clickConfirmSavedSearch() {
await testSubjects.click('confirmSaveSavedObjectButton');
}
- async openAddFilterPanel() {
+ public async openAddFilterPanel() {
await testSubjects.click('addFilter');
}
- async waitUntilSearchingHasFinished() {
+ public async waitUntilSearchingHasFinished() {
const spinner = await testSubjects.find('loadingSpinner');
await find.waitForElementHidden(spinner, defaultFindTimeout * 10);
}
- async getColumnHeaders() {
- const headerElements = await testSubjects.findAll('docTableHeaderField');
- return await Promise.all(headerElements.map(async el => await el.getVisibleText()));
+ public async getColumnHeaders() {
+ return await docTable.getHeaderFields('embeddedSavedSearchDocTable');
}
- async openLoadSavedSearchPanel() {
- const isOpen = await testSubjects.exists('loadSearchForm');
+ public async openLoadSavedSearchPanel() {
+ let isOpen = await testSubjects.exists('loadSearchForm');
if (isOpen) {
return;
}
@@ -95,55 +88,47 @@ export function DiscoverPageProvider({ getService, getPageObjects }) {
// saving a search cause reloading of the page and the "Open" menu item goes stale.
await retry.try(async () => {
await this.clickLoadSavedSearchButton();
- await PageObjects.header.waitUntilLoadingHasFinished();
- const isOpen = await testSubjects.exists('loadSearchForm');
+ await header.waitUntilLoadingHasFinished();
+ isOpen = await testSubjects.exists('loadSearchForm');
expect(isOpen).to.be(true);
});
}
- async closeLoadSaveSearchPanel() {
+ public async closeLoadSaveSearchPanel() {
await flyout.ensureClosed('loadSearchForm');
}
- async hasSavedSearch(searchName) {
+ public async hasSavedSearch(searchName: string) {
const searchLink = await find.byButtonText(searchName);
- return searchLink.isDisplayed();
+ return await searchLink.isDisplayed();
}
- async loadSavedSearch(searchName) {
+ public async loadSavedSearch(searchName: string) {
await this.openLoadSavedSearchPanel();
const searchLink = await find.byButtonText(searchName);
await searchLink.click();
- await PageObjects.header.waitUntilLoadingHasFinished();
+ await header.waitUntilLoadingHasFinished();
}
- async clickNewSearchButton() {
+ public async clickNewSearchButton() {
await testSubjects.click('discoverNewButton');
}
- async clickSaveSearchButton() {
+ public async clickSaveSearchButton() {
await testSubjects.click('discoverSaveButton');
}
- async clickLoadSavedSearchButton() {
+ public async clickLoadSavedSearchButton() {
await testSubjects.moveMouseTo('discoverOpenButton');
await testSubjects.click('discoverOpenButton');
}
- async closeLoadSavedSearchPanel() {
+ public async closeLoadSavedSearchPanel() {
await testSubjects.click('euiFlyoutCloseButton');
}
- async getChartCanvas() {
- return await find.byCssSelector('.echChart canvas:last-of-type');
- }
-
- async chartCanvasExist() {
- return await find.existsByCssSelector('.echChart canvas:last-of-type');
- }
-
- async clickHistogramBar() {
- const el = await this.getChartCanvas();
+ public async clickHistogramBar() {
+ const el = await elasticChart.getCanvas();
await browser
.getActions()
@@ -152,8 +137,8 @@ export function DiscoverPageProvider({ getService, getPageObjects }) {
.perform();
}
- async brushHistogram() {
- const el = await this.getChartCanvas();
+ public async brushHistogram() {
+ const el = await elasticChart.getCanvas();
await browser.dragAndDrop(
{ location: el, offset: { x: 200, y: 20 } },
@@ -161,169 +146,154 @@ export function DiscoverPageProvider({ getService, getPageObjects }) {
);
}
- async getCurrentQueryName() {
+ public async getCurrentQueryName() {
return await globalNav.getLastBreadcrumb();
}
- async getBarChartData() {
- let yAxisLabel = 0;
-
- await PageObjects.header.waitUntilLoadingHasFinished();
- const y = await find.byCssSelector(
- 'div.visAxis__splitAxes--y > div > svg > g > g:last-of-type'
- );
- const yLabel = await y.getVisibleText();
- yAxisLabel = yLabel.replace(',', '');
- log.debug('yAxisLabel = ' + yAxisLabel);
- // #kibana-body > div.content > div > div > div > div.visEditor__canvas > visualize > div.visChart > div > div.visWrapper__column > div.visWrapper__chart > div > svg > g > g.series.\30 > rect:nth-child(1)
- const svg = await find.byCssSelector('div.chart > svg');
- const $ = await svg.parseDomContent();
- const yAxisHeight = $('rect.background').attr('height');
- log.debug('theHeight = ' + yAxisHeight);
- const bars = $('g > g.series > rect')
- .toArray()
- .map(chart => {
- const barHeight = $(chart).attr('height');
- return Math.round((barHeight / yAxisHeight) * yAxisLabel);
- });
-
- return bars;
- }
-
- async getChartInterval() {
+ public async getChartInterval() {
const selectedValue = await testSubjects.getAttribute('discoverIntervalSelect', 'value');
- const selectedOption = await find.byCssSelector('option[value="' + selectedValue + '"]');
+ const selectedOption = await find.byCssSelector(`option[value="${selectedValue}"]`);
return selectedOption.getVisibleText();
}
- async setChartInterval(interval) {
- const optionElement = await find.byCssSelector('option[label="' + interval + '"]', 5000);
+ public async setChartInterval(interval: string) {
+ const optionElement = await find.byCssSelector(`option[label="${interval}"]`, 5000);
await optionElement.click();
- return await PageObjects.header.waitUntilLoadingHasFinished();
+ return await header.waitUntilLoadingHasFinished();
}
- async getHitCount() {
- await PageObjects.header.waitUntilLoadingHasFinished();
+ public async getHitCount() {
+ await header.waitUntilLoadingHasFinished();
return await testSubjects.getVisibleText('discoverQueryHits');
}
- async getDocHeader() {
- const header = await find.byCssSelector('thead > tr:nth-child(1)');
- return await header.getVisibleText();
+ public async getDocHeader() {
+ const docHeader = await find.byCssSelector('thead > tr:nth-child(1)');
+ return await docHeader.getVisibleText();
}
- async getDocTableIndex(index) {
- const row = await find.byCssSelector('tr.kbnDocTable__row:nth-child(' + index + ')');
+ public async getDocTableIndex(index: number) {
+ const row = await find.byCssSelector(`tr.kbnDocTable__row:nth-child(${index})`);
return await row.getVisibleText();
}
- async getDocTableField(index) {
+ public async getDocTableField(index: number) {
const field = await find.byCssSelector(
`tr.kbnDocTable__row:nth-child(${index}) > [data-test-subj='docTableField']`
);
return await field.getVisibleText();
}
- async clickDocSortDown() {
+ public async clickDocSortDown() {
await find.clickByCssSelector('.fa-sort-down');
}
- async clickDocSortUp() {
+ public async clickDocSortUp() {
await find.clickByCssSelector('.fa-sort-up');
}
- async getMarks() {
- const marks = await find.allByCssSelector('mark');
- return await Promise.all(marks.map(mark => mark.getVisibleText()));
+ public async getMarks() {
+ const table = await docTable.getTable();
+ const $ = await table.parseDomContent();
+ return $('mark')
+ .toArray()
+ .map(mark => $(mark).text());
}
- async toggleSidebarCollapse() {
+ public async toggleSidebarCollapse() {
return await testSubjects.click('collapseSideBarButton');
}
- async getAllFieldNames() {
- const items = await find.allByCssSelector('.sidebar-item');
- return await Promise.all(items.map(item => item.getVisibleText()));
+ public async getAllFieldNames() {
+ const sidebar = await testSubjects.find('discover-sidebar');
+ const $ = await sidebar.parseDomContent();
+ return $('.sidebar-item[attr-field]')
+ .toArray()
+ .map(field =>
+ $(field)
+ .find('span.eui-textTruncate')
+ .text()
+ );
}
- async getSidebarWidth() {
+ public async getSidebarWidth() {
const sidebar = await find.byCssSelector('.sidebar-list');
return await sidebar.getAttribute('clientWidth');
}
- async hasNoResults() {
+ public async hasNoResults() {
return await testSubjects.exists('discoverNoResults');
}
- async hasNoResultsTimepicker() {
+ public async hasNoResultsTimepicker() {
return await testSubjects.exists('discoverNoResultsTimefilter');
}
- async clickFieldListItem(field) {
+ public async clickFieldListItem(field: string) {
return await testSubjects.click(`field-${field}`);
}
- async clickFieldListItemAdd(field) {
+ public async clickFieldListItemAdd(field: string) {
await testSubjects.moveMouseTo(`field-${field}`);
await testSubjects.click(`fieldToggle-${field}`);
}
- async clickFieldListItemVisualize(field) {
+ public async clickFieldListItemVisualize(field: string) {
return await retry.try(async () => {
await testSubjects.click(`fieldVisualize-${field}`);
});
}
- async expectFieldListItemVisualize(field) {
+ public async expectFieldListItemVisualize(field: string) {
await testSubjects.existOrFail(`fieldVisualize-${field}`);
}
- async expectMissingFieldListItemVisualize(field) {
+ public async expectMissingFieldListItemVisualize(field: string) {
await testSubjects.missingOrFail(`fieldVisualize-${field}`, { allowHidden: true });
}
- async clickFieldListPlusFilter(field, value) {
+ public async clickFieldListPlusFilter(field: string, value: string) {
// this method requires the field details to be open from clickFieldListItem()
// testSubjects.find doesn't handle spaces in the data-test-subj value
await find.clickByCssSelector(`[data-test-subj="plus-${field}-${value}"]`);
- await PageObjects.header.waitUntilLoadingHasFinished();
+ await header.waitUntilLoadingHasFinished();
}
- async clickFieldListMinusFilter(field, value) {
+ public async clickFieldListMinusFilter(field: string, value: string) {
// this method requires the field details to be open from clickFieldListItem()
// testSubjects.find doesn't handle spaces in the data-test-subj value
await find.clickByCssSelector('[data-test-subj="minus-' + field + '-' + value + '"]');
- await PageObjects.header.waitUntilLoadingHasFinished();
+ await header.waitUntilLoadingHasFinished();
}
- async selectIndexPattern(indexPattern) {
+ public async selectIndexPattern(indexPattern: string) {
await testSubjects.click('indexPattern-switch-link');
await find.clickByCssSelector(
`[data-test-subj="indexPattern-switcher"] [title="${indexPattern}"]`
);
- await PageObjects.header.waitUntilLoadingHasFinished();
+ await header.waitUntilLoadingHasFinished();
}
- async removeHeaderColumn(name) {
+ public async removeHeaderColumn(name: string) {
await testSubjects.moveMouseTo(`docTableHeader-${name}`);
await testSubjects.click(`docTableRemoveHeader-${name}`);
}
- async openSidebarFieldFilter() {
+ public async openSidebarFieldFilter() {
await testSubjects.click('toggleFieldFilterButton');
await testSubjects.existOrFail('filterSelectionPanel');
}
- async closeSidebarFieldFilter() {
+ public async closeSidebarFieldFilter() {
await testSubjects.click('toggleFieldFilterButton');
await testSubjects.missingOrFail('filterSelectionPanel', { allowHidden: true });
}
- async waitForChartLoadingComplete(renderCount) {
+ public async waitForChartLoadingComplete(renderCount: number) {
await elasticChart.waitForRenderingCount('discoverChart', renderCount);
}
- async waitForDocTableLoadingComplete() {
+ public async waitForDocTableLoadingComplete() {
await testSubjects.waitForAttributeToChange(
'discoverDocTable',
'data-render-complete',
diff --git a/test/functional/page_objects/index.ts b/test/functional/page_objects/index.ts
index 4ba8ddb035913..db58c3c2c7d19 100644
--- a/test/functional/page_objects/index.ts
+++ b/test/functional/page_objects/index.ts
@@ -23,13 +23,11 @@ import { ConsolePageProvider } from './console_page';
// @ts-ignore not TS yet
import { ContextPageProvider } from './context_page';
import { DashboardPageProvider } from './dashboard_page';
-// @ts-ignore not TS yet
import { DiscoverPageProvider } from './discover_page';
// @ts-ignore not TS yet
import { ErrorPageProvider } from './error_page';
// @ts-ignore not TS yet
import { HeaderPageProvider } from './header_page';
-// @ts-ignore not TS yet
import { HomePageProvider } from './home_page';
// @ts-ignore not TS yet
import { MonitoringPageProvider } from './monitoring_page';
diff --git a/test/functional/services/doc_table.ts b/test/functional/services/doc_table.ts
index 2530831e0f6f9..cb3daf20c641a 100644
--- a/test/functional/services/doc_table.ts
+++ b/test/functional/services/doc_table.ts
@@ -30,8 +30,8 @@ export function DocTableProvider({ getService, getPageObjects }: FtrProviderCont
}
class DocTable {
- public async getTable() {
- return await testSubjects.find('docTable');
+ public async getTable(selector?: string) {
+ return await testSubjects.find(selector ? selector : 'docTable');
}
public async getRowsText() {
@@ -106,8 +106,8 @@ export function DocTableProvider({ getService, getPageObjects }: FtrProviderCont
);
}
- public async getHeaderFields(): Promise {
- const table = await this.getTable();
+ public async getHeaderFields(selector?: string): Promise {
+ const table = await this.getTable(selector);
const $ = await table.parseDomContent();
return $.findTestSubjects('~docTableHeaderField')
.toArray()
diff --git a/test/functional/services/elastic_chart.ts b/test/functional/services/elastic_chart.ts
index afae3f830b3bf..45ad157fc5c02 100644
--- a/test/functional/services/elastic_chart.ts
+++ b/test/functional/services/elastic_chart.ts
@@ -22,10 +22,19 @@ import { FtrProviderContext } from '../ftr_provider_context';
export function ElasticChartProvider({ getService }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
+ const find = getService('find');
const retry = getService('retry');
const log = getService('log');
class ElasticChart {
+ public async getCanvas() {
+ return await find.byCssSelector('.echChart canvas:last-of-type');
+ }
+
+ public async canvasExists() {
+ return await find.existsByCssSelector('.echChart canvas:last-of-type');
+ }
+
public async waitForRenderComplete(dataTestSubj: string) {
const chart = await testSubjects.find(dataTestSubj);
const rendered = await chart.findAllByCssSelector('.echChart[data-ech-render-complete=true]');
diff --git a/x-pack/legacy/plugins/transform/public/__mocks__/shared_imports.ts b/x-pack/legacy/plugins/transform/public/__mocks__/shared_imports.ts
index aa130b5030fc7..d7fca9820e614 100644
--- a/x-pack/legacy/plugins/transform/public/__mocks__/shared_imports.ts
+++ b/x-pack/legacy/plugins/transform/public/__mocks__/shared_imports.ts
@@ -6,12 +6,14 @@
jest.mock('ui/new_platform');
-export function XJsonMode() {}
-export function setDependencyCache() {}
-export const useRequest = () => ({
+export const expandLiteralStrings = jest.fn();
+export const XJsonMode = jest.fn();
+export const setDependencyCache = jest.fn();
+export const useRequest = jest.fn(() => ({
isLoading: false,
error: null,
data: undefined,
-});
+}));
export { mlInMemoryTableBasicFactory } from '../../../ml/public/application/components/ml_in_memory_table';
export const SORT_DIRECTION = { ASC: 'asc' };
+export const KqlFilterBar = jest.fn(() => null);
diff --git a/x-pack/legacy/plugins/transform/public/app/common/request.ts b/x-pack/legacy/plugins/transform/public/app/common/request.ts
index 3b740de177ef8..31089b86a2c2d 100644
--- a/x-pack/legacy/plugins/transform/public/app/common/request.ts
+++ b/x-pack/legacy/plugins/transform/public/app/common/request.ts
@@ -7,7 +7,7 @@
import { DefaultOperator } from 'elasticsearch';
import { dictionaryToArray } from '../../../common/types/common';
-import { SavedSearchQuery } from '../lib/kibana';
+import { SavedSearchQuery } from '../hooks/use_search_items';
import { StepDefineExposedState } from '../sections/create_transform/components/step_define/step_define_form';
import { StepDetailsExposedState } from '../sections/create_transform/components/step_details/step_details_form';
diff --git a/x-pack/legacy/plugins/transform/public/app/components/toast_notification_text.test.tsx b/x-pack/legacy/plugins/transform/public/app/components/toast_notification_text.test.tsx
index 81af5c974fe04..095b57de97d9a 100644
--- a/x-pack/legacy/plugins/transform/public/app/components/toast_notification_text.test.tsx
+++ b/x-pack/legacy/plugins/transform/public/app/components/toast_notification_text.test.tsx
@@ -7,13 +7,13 @@
import React from 'react';
import { render } from '@testing-library/react';
-import { KibanaContext } from '../lib/kibana';
import { createPublicShim } from '../../shim';
import { getAppProviders } from '../app_dependencies';
import { ToastNotificationText } from './toast_notification_text';
jest.mock('../../shared_imports');
+jest.mock('ui/new_platform');
describe('ToastNotificationText', () => {
test('should render the text as plain text', () => {
@@ -23,9 +23,7 @@ describe('ToastNotificationText', () => {
};
const { container } = render(
-
-
-
+
);
expect(container.textContent).toBe('a short text message');
@@ -39,9 +37,7 @@ describe('ToastNotificationText', () => {
};
const { container } = render(
-
-
-
+
);
expect(container.textContent).toBe(
diff --git a/x-pack/legacy/plugins/transform/public/app/lib/kibana/common.ts b/x-pack/legacy/plugins/transform/public/app/hooks/use_search_items/common.ts
similarity index 96%
rename from x-pack/legacy/plugins/transform/public/app/lib/kibana/common.ts
rename to x-pack/legacy/plugins/transform/public/app/hooks/use_search_items/common.ts
index aa4cd21281e22..2258f8f33f01d 100644
--- a/x-pack/legacy/plugins/transform/public/app/lib/kibana/common.ts
+++ b/x-pack/legacy/plugins/transform/public/app/hooks/use_search_items/common.ts
@@ -14,6 +14,8 @@ import {
import { matchAllQuery } from '../../common';
+export type SavedSearchQuery = object;
+
type IndexPatternId = string;
type SavedSearchId = string;
@@ -60,7 +62,7 @@ export function getIndexPatternIdByTitle(indexPatternTitle: string): string | un
return indexPatternCache.find(d => d?.attributes?.title === indexPatternTitle)?.id;
}
-type CombinedQuery = Record<'bool', any> | unknown;
+type CombinedQuery = Record<'bool', any> | object;
export function loadCurrentIndexPattern(
indexPatterns: IndexPatternsContract,
@@ -79,17 +81,20 @@ export function loadCurrentSavedSearch(savedSearches: any, savedSearchId: SavedS
function isIndexPattern(arg: any): arg is IndexPattern {
return arg !== undefined;
}
+
+export interface SearchItems {
+ indexPattern: IndexPattern;
+ savedSearch: any;
+ query: any;
+ combinedQuery: CombinedQuery;
+}
+
// Helper for creating the items used for searching and job creation.
export function createSearchItems(
indexPattern: IndexPattern | undefined,
savedSearch: any,
config: IUiSettingsClient
-): {
- indexPattern: IndexPattern;
- savedSearch: any;
- query: any;
- combinedQuery: CombinedQuery;
-} {
+): SearchItems {
// query is only used by the data visualizer as it needs
// a lucene query_string.
// Using a blank query will cause match_all:{} to be used
diff --git a/x-pack/legacy/plugins/transform/public/app/hooks/use_search_items/index.ts b/x-pack/legacy/plugins/transform/public/app/hooks/use_search_items/index.ts
new file mode 100644
index 0000000000000..aa4f04f43b335
--- /dev/null
+++ b/x-pack/legacy/plugins/transform/public/app/hooks/use_search_items/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;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { SavedSearchQuery, SearchItems } from './common';
+export { useSearchItems } from './use_search_items';
diff --git a/x-pack/legacy/plugins/transform/public/app/lib/kibana/kibana_provider.tsx b/x-pack/legacy/plugins/transform/public/app/hooks/use_search_items/use_search_items.ts
similarity index 53%
rename from x-pack/legacy/plugins/transform/public/app/lib/kibana/kibana_provider.tsx
rename to x-pack/legacy/plugins/transform/public/app/hooks/use_search_items/use_search_items.ts
index f2574a4a85f29..12fc75c20ffa4 100644
--- a/x-pack/legacy/plugins/transform/public/app/lib/kibana/kibana_provider.tsx
+++ b/x-pack/legacy/plugins/transform/public/app/hooks/use_search_items/use_search_items.ts
@@ -4,30 +4,36 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { useEffect, useState, FC } from 'react';
+import { useEffect, useState } from 'react';
+
+import { createSavedSearchesLoader } from '../../../shared_imports';
import { useAppDependencies } from '../../app_dependencies';
import {
createSearchItems,
+ getIndexPatternIdByTitle,
loadCurrentIndexPattern,
loadIndexPatterns,
loadCurrentSavedSearch,
+ SearchItems,
} from './common';
-import { InitializedKibanaContextValue, KibanaContext, KibanaContextValue } from './kibana_context';
-
-interface Props {
- savedObjectId: string;
-}
+export const useSearchItems = (defaultSavedObjectId: string | undefined) => {
+ const [savedObjectId, setSavedObjectId] = useState(defaultSavedObjectId);
-export const KibanaProvider: FC = ({ savedObjectId, children }) => {
const appDeps = useAppDependencies();
const indexPatterns = appDeps.plugins.data.indexPatterns;
+ const uiSettings = appDeps.core.uiSettings;
const savedObjectsClient = appDeps.core.savedObjects.client;
- const savedSearches = appDeps.plugins.savedSearches.getClient();
+ const savedSearches = createSavedSearchesLoader({
+ savedObjectsClient,
+ indexPatterns,
+ chrome: appDeps.core.chrome,
+ overlays: appDeps.core.overlays,
+ });
- const [contextValue, setContextValue] = useState({ initialized: false });
+ const [searchItems, setSearchItems] = useState(undefined);
async function fetchSavedObject(id: string) {
await loadIndexPatterns(savedObjectsClient, indexPatterns);
@@ -47,31 +53,21 @@ export const KibanaProvider: FC = ({ savedObjectId, children }) => {
// Just let fetchedSavedSearch stay undefined in case it doesn't exist.
}
- const kibanaConfig = appDeps.core.uiSettings;
-
- const {
- indexPattern: currentIndexPattern,
- savedSearch: currentSavedSearch,
- combinedQuery,
- } = createSearchItems(fetchedIndexPattern, fetchedSavedSearch, kibanaConfig);
-
- const kibanaContext: InitializedKibanaContextValue = {
- indexPatterns,
- initialized: true,
- kibanaConfig,
- combinedQuery,
- currentIndexPattern,
- currentSavedSearch,
- };
-
- setContextValue(kibanaContext);
+ setSearchItems(createSearchItems(fetchedIndexPattern, fetchedSavedSearch, uiSettings));
}
useEffect(() => {
- fetchSavedObject(savedObjectId);
- // fetchSavedObject should not be tracked.
+ if (savedObjectId !== undefined) {
+ fetchSavedObject(savedObjectId);
+ }
+ // Run this only when savedObjectId changes.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [savedObjectId]);
- return {children} ;
+ return {
+ getIndexPatternIdByTitle,
+ loadIndexPatterns,
+ searchItems,
+ setSavedObjectId,
+ };
};
diff --git a/x-pack/legacy/plugins/transform/public/app/lib/kibana/index.ts b/x-pack/legacy/plugins/transform/public/app/lib/kibana/index.ts
deleted file mode 100644
index 62107cb37ff2c..0000000000000
--- a/x-pack/legacy/plugins/transform/public/app/lib/kibana/index.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * 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 { getIndexPatternIdByTitle, loadIndexPatterns } from './common';
-export {
- useKibanaContext,
- InitializedKibanaContextValue,
- KibanaContext,
- KibanaContextValue,
- SavedSearchQuery,
- RenderOnlyWithInitializedKibanaContext,
-} from './kibana_context';
-export { KibanaProvider } from './kibana_provider';
-export { useCurrentIndexPattern } from './use_current_index_pattern';
diff --git a/x-pack/legacy/plugins/transform/public/app/lib/kibana/kibana_context.tsx b/x-pack/legacy/plugins/transform/public/app/lib/kibana/kibana_context.tsx
deleted file mode 100644
index 7677c491a7a59..0000000000000
--- a/x-pack/legacy/plugins/transform/public/app/lib/kibana/kibana_context.tsx
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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 React, { createContext, useContext, FC } from 'react';
-
-import { IUiSettingsClient } from 'kibana/public';
-
-import {
- IndexPattern,
- IndexPatternsContract,
-} from '../../../../../../../../src/plugins/data/public';
-import { SavedSearch } from '../../../../../../../../src/plugins/discover/public/';
-
-interface UninitializedKibanaContextValue {
- initialized: false;
-}
-
-export interface InitializedKibanaContextValue {
- combinedQuery: any;
- indexPatterns: IndexPatternsContract;
- initialized: true;
- kibanaConfig: IUiSettingsClient;
- currentIndexPattern: IndexPattern;
- currentSavedSearch?: SavedSearch;
-}
-
-export type KibanaContextValue = UninitializedKibanaContextValue | InitializedKibanaContextValue;
-
-export function isKibanaContextInitialized(arg: any): arg is InitializedKibanaContextValue {
- return arg.initialized;
-}
-
-export type SavedSearchQuery = object;
-
-export const KibanaContext = createContext({ initialized: false });
-
-/**
- * Custom hook to get the current kibanaContext.
- *
- * @remarks
- * This hook should only be used in components wrapped in `RenderOnlyWithInitializedKibanaContext`,
- * otherwise it will throw an error when KibanaContext hasn't been initialized yet.
- * In return you get the benefit of not having to check if it's been initialized in the component
- * where it's used.
- *
- * @returns `kibanaContext`
- */
-export const useKibanaContext = () => {
- const kibanaContext = useContext(KibanaContext);
-
- if (!isKibanaContextInitialized(kibanaContext)) {
- throw new Error('useKibanaContext: kibanaContext not initialized');
- }
-
- return kibanaContext;
-};
-
-/**
- * Wrapper component to render children only if `kibanaContext` has been initialized.
- * In combination with `useKibanaContext` this avoids having to check for the initialization
- * in consuming components.
- *
- * @returns `children` or `null` depending on whether `kibanaContext` is initialized or not.
- */
-export const RenderOnlyWithInitializedKibanaContext: FC = ({ children }) => {
- const kibanaContext = useContext(KibanaContext);
-
- return isKibanaContextInitialized(kibanaContext) ? <>{children}> : null;
-};
diff --git a/x-pack/legacy/plugins/transform/public/app/lib/kibana/use_current_index_pattern.ts b/x-pack/legacy/plugins/transform/public/app/lib/kibana/use_current_index_pattern.ts
deleted file mode 100644
index 12c5bde171b8b..0000000000000
--- a/x-pack/legacy/plugins/transform/public/app/lib/kibana/use_current_index_pattern.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import { useContext } from 'react';
-
-import { isKibanaContextInitialized, KibanaContext } from './kibana_context';
-
-export const useCurrentIndexPattern = () => {
- const context = useContext(KibanaContext);
-
- if (!isKibanaContextInitialized(context)) {
- throw new Error('useCurrentIndexPattern: kibanaContext not initialized');
- }
-
- return context.currentIndexPattern;
-};
diff --git a/x-pack/legacy/plugins/transform/public/app/sections/clone_transform/clone_transform_section.tsx b/x-pack/legacy/plugins/transform/public/app/sections/clone_transform/clone_transform_section.tsx
index c5c46dcac6c95..4618e96cbfd6e 100644
--- a/x-pack/legacy/plugins/transform/public/app/sections/clone_transform/clone_transform_section.tsx
+++ b/x-pack/legacy/plugins/transform/public/app/sections/clone_transform/clone_transform_section.tsx
@@ -22,6 +22,7 @@ import {
} from '@elastic/eui';
import { useApi } from '../../hooks/use_api';
+import { useSearchItems } from '../../hooks/use_search_items';
import { APP_CREATE_TRANSFORM_CLUSTER_PRIVILEGES } from '../../../../common/constants';
@@ -29,12 +30,6 @@ import { useAppDependencies, useDocumentationLinks } from '../../app_dependencie
import { TransformPivotConfig } from '../../common';
import { breadcrumbService, docTitleService, BREADCRUMB_SECTION } from '../../services/navigation';
import { PrivilegesWrapper } from '../../lib/authorization';
-import {
- getIndexPatternIdByTitle,
- loadIndexPatterns,
- KibanaProvider,
- RenderOnlyWithInitializedKibanaContext,
-} from '../../lib/kibana';
import { Wizard } from '../create_transform/components/wizard';
@@ -80,7 +75,12 @@ export const CloneTransformSection: FC = ({ match }) => {
const [transformConfig, setTransformConfig] = useState();
const [errorMessage, setErrorMessage] = useState();
const [isInitialized, setIsInitialized] = useState(false);
- const [savedObjectId, setSavedObjectId] = useState(undefined);
+ const {
+ getIndexPatternIdByTitle,
+ loadIndexPatterns,
+ searchItems,
+ setSavedObjectId,
+ } = useSearchItems(undefined);
const fetchTransformConfig = async () => {
try {
@@ -169,12 +169,8 @@ export const CloneTransformSection: FC = ({ match }) => {
-
-
-
-
+ {searchItems !== undefined && isInitialized === true && transformConfig !== undefined && (
+
)}
diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/source_index_preview/__snapshots__/source_index_preview.test.tsx.snap b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/source_index_preview/__snapshots__/source_index_preview.test.tsx.snap
deleted file mode 100644
index e43f2e37bb416..0000000000000
--- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/source_index_preview/__snapshots__/source_index_preview.test.tsx.snap
+++ /dev/null
@@ -1,24 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Transform: Minimal initialization 1`] = `
- ', () => {
},
};
- // Using a wrapping
{JSON.stringify(errorMessage)})} - {savedObjectId !== undefined && isInitialized === true && transformConfig !== undefined && ( -
-
-
-
-
-`;
diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/source_index_preview/expanded_row.test.tsx b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/source_index_preview/expanded_row.test.tsx
index bfde8f171874e..ddd1a1482fd35 100644
--- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/source_index_preview/expanded_row.test.tsx
+++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/source_index_preview/expanded_row.test.tsx
@@ -39,8 +39,6 @@ describe('Transform: element because shallow() would fail
- // with the Provider being the outer most component.
const wrapper = shallow( );
expect(wrapper).toMatchSnapshot();
diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/source_index_preview/source_index_preview.test.tsx b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/source_index_preview/source_index_preview.test.tsx
index 16949425284fd..48eff132cd753 100644
--- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/source_index_preview/source_index_preview.test.tsx
+++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/source_index_preview/source_index_preview.test.tsx
@@ -4,38 +4,39 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { shallow } from 'enzyme';
import React from 'react';
+import { render } from '@testing-library/react';
+import '@testing-library/jest-dom/extend-expect';
-import { KibanaContext } from '../../../../lib/kibana';
+import { createPublicShim } from '../../../../../shim';
+import { getAppProviders } from '../../../../app_dependencies';
import { getPivotQuery } from '../../../../common';
+import { SearchItems } from '../../../../hooks/use_search_items';
import { SourceIndexPreview } from './source_index_preview';
-// workaround to make React.memo() work with enzyme
-jest.mock('react', () => {
- const r = jest.requireActual('react');
- return { ...r, memo: (x: any) => x };
-});
-
+jest.mock('ui/new_platform');
jest.mock('../../../../../shared_imports');
describe('Transform: ', () => {
test('Minimal initialization', () => {
+ // Arrange
const props = {
+ indexPattern: {
+ title: 'the-index-pattern-title',
+ fields: [] as any[],
+ } as SearchItems['indexPattern'],
query: getPivotQuery('the-query'),
};
-
- // Using a wrapping
element because shallow() would fail
- // with the Provider being the outer most component.
- const wrapper = shallow(
-
+
+
);
- expect(wrapper).toMatchSnapshot();
+ // Act
+ // Assert
+ expect(getByText(`Source index ${props.indexPattern.title}`)).toBeInTheDocument();
});
});
diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/source_index_preview/source_index_preview.tsx b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/source_index_preview/source_index_preview.tsx
index 0c9dcfb9b1c04..76ed12ff772f5 100644
--- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/source_index_preview/source_index_preview.tsx
+++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/source_index_preview/source_index_preview.tsx
@@ -22,14 +22,13 @@ import {
import { getNestedProperty } from '../../../../../../common/utils/object_utils';
-import { useCurrentIndexPattern } from '../../../../lib/kibana';
-
import {
euiDataGridStyle,
euiDataGridToolbarSettings,
EsFieldName,
PivotQuery,
} from '../../../../common';
+import { SearchItems } from '../../../../hooks/use_search_items';
import { getSourceIndexDevConsoleStatement } from './common';
import { SOURCE_INDEX_STATUS, useSourceIndexData } from './use_source_index_data';
@@ -49,13 +48,13 @@ const SourceIndexPreviewTitle: React.FC = ({ indexPatte
);
interface Props {
+ indexPattern: SearchItems['indexPattern'];
query: PivotQuery;
}
const defaultPagination = { pageIndex: 0, pageSize: 5 };
-export const SourceIndexPreview: React.FC = React.memo(({ query }) => {
- const indexPattern = useCurrentIndexPattern();
+export const SourceIndexPreview: React.FC = React.memo(({ indexPattern, query }) => {
const allFields = indexPattern.fields.map(f => f.name);
const indexPatternFields: string[] = allFields.filter(f => {
if (indexPattern.metaFields.includes(f)) {
diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_create/__snapshots__/step_create_form.test.tsx.snap b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_create/__snapshots__/step_create_form.test.tsx.snap
deleted file mode 100644
index e034badea9b11..0000000000000
--- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_create/__snapshots__/step_create_form.test.tsx.snap
+++ /dev/null
@@ -1,27 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Transform: Minimal initialization 1`] = `
- ', () => {
test('Minimal initialization', () => {
+ // Arrange
const props = {
createIndexPattern: false,
transformId: 'the-transform-id',
@@ -29,16 +27,15 @@ describe('Transform: ', () => {
onChange() {},
};
- // Using a wrapping
-
-
-
-
+ const Providers = getAppProviders(createPublicShim());
+ const { getByText } = render(
+
-
-
-
-
-`;
diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.test.tsx b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.test.tsx
index 625c545ee8c46..7a22af492e36e 100644
--- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.test.tsx
+++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.test.tsx
@@ -4,23 +4,21 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { shallow } from 'enzyme';
import React from 'react';
+import { render } from '@testing-library/react';
+import '@testing-library/jest-dom/extend-expect';
-import { KibanaContext } from '../../../../lib/kibana';
+import { createPublicShim } from '../../../../../shim';
+import { getAppProviders } from '../../../../app_dependencies';
import { StepCreateForm } from './step_create_form';
-// workaround to make React.memo() work with enzyme
-jest.mock('react', () => {
- const r = jest.requireActual('react');
- return { ...r, memo: (x: any) => x };
-});
-
+jest.mock('ui/new_platform');
jest.mock('../../../../../shared_imports');
describe('Transform: element because shallow() would fail
- // with the Provider being the outer most component.
- const wrapper = shallow(
-
+
+
);
- expect(wrapper).toMatchSnapshot();
+ // Act
+ // Assert
+ expect(getByText('Create and start')).toBeInTheDocument();
});
});
diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx
index bbeb97b6b8113..4198c2ea0260d 100644
--- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx
+++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx
@@ -34,7 +34,6 @@ import { PROGRESS_REFRESH_INTERVAL_MS } from '../../../../../../common/constants
import { getTransformProgress, getDiscoverUrl } from '../../../../common';
import { useApi } from '../../../../hooks/use_api';
-import { useKibanaContext } from '../../../../lib/kibana';
import { useAppDependencies, useToastNotifications } from '../../../../app_dependencies';
import { RedirectToTransformManagement } from '../../../../common/navigation';
import { ToastNotificationText } from '../../../../components';
@@ -76,7 +75,8 @@ export const StepCreateForm: FC = React.memo(
);
const deps = useAppDependencies();
- const kibanaContext = useKibanaContext();
+ const indexPatterns = deps.plugins.data.indexPatterns;
+ const uiSettings = deps.core.uiSettings;
const toastNotifications = useToastNotifications();
useEffect(() => {
@@ -176,7 +176,7 @@ export const StepCreateForm: FC = React.memo(
const indexPatternName = transformConfig.dest.index;
try {
- const newIndexPattern = await kibanaContext.indexPatterns.make();
+ const newIndexPattern = await indexPatterns.make();
Object.assign(newIndexPattern, {
id: '',
@@ -200,8 +200,8 @@ export const StepCreateForm: FC = React.memo(
// check if there's a default index pattern, if not,
// set the newly created one as the default index pattern.
- if (!kibanaContext.kibanaConfig.get('defaultIndex')) {
- await kibanaContext.kibanaConfig.set('defaultIndex', id);
+ if (!uiSettings.get('defaultIndex')) {
+ await uiSettings.set('defaultIndex', id);
}
toastNotifications.addSuccess(
diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/__snapshots__/pivot_preview.test.tsx.snap b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/__snapshots__/pivot_preview.test.tsx.snap
deleted file mode 100644
index a7da172a67b8a..0000000000000
--- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/__snapshots__/pivot_preview.test.tsx.snap
+++ /dev/null
@@ -1,44 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Transform: Minimal initialization 1`] = `
- Minimal initialization 1`] = `
- Minimal initialization 1`] = `
- ', () => {
test('Minimal initialization', () => {
+ // Arrange
const groupBy: PivotGroupByConfig = {
agg: PIVOT_SUPPORTED_GROUP_BY_AGGS.TERMS,
field: 'the-group-by-field',
@@ -44,19 +42,22 @@ describe('Transform: ', () => {
const props = {
aggs: { 'the-agg-name': agg },
groupBy: { 'the-group-by-name': groupBy },
+ indexPattern: {
+ title: 'the-index-pattern-title',
+ fields: [] as any[],
+ } as SearchItems['indexPattern'],
query: getPivotQuery('the-query'),
};
- // Using a wrapping
-
-
-
-
+ const Providers = getAppProviders(createPublicShim());
+ const { getByText } = render(
+
-
-
-
-
-`;
diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/__snapshots__/step_define_form.test.tsx.snap b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/__snapshots__/step_define_form.test.tsx.snap
deleted file mode 100644
index 70a0bfc12b208..0000000000000
--- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/__snapshots__/step_define_form.test.tsx.snap
+++ /dev/null
@@ -1,17 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Transform:
-
-
-
-
-`;
diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/__snapshots__/step_define_summary.test.tsx.snap b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/__snapshots__/step_define_summary.test.tsx.snap
deleted file mode 100644
index b18233e5c53e3..0000000000000
--- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/__snapshots__/step_define_summary.test.tsx.snap
+++ /dev/null
@@ -1,42 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Transform:
-
-
-
-
-`;
diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/pivot_preview.test.tsx b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/pivot_preview.test.tsx
index 2ac4295da1eed..464b6e1fd9fe3 100644
--- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/pivot_preview.test.tsx
+++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/pivot_preview.test.tsx
@@ -4,11 +4,12 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { shallow } from 'enzyme';
import React from 'react';
+import { render } from '@testing-library/react';
+import '@testing-library/jest-dom/extend-expect';
-import { KibanaContext } from '../../../../lib/kibana';
-
+import { createPublicShim } from '../../../../../shim';
+import { getAppProviders } from '../../../../app_dependencies';
import {
getPivotQuery,
PivotAggsConfig,
@@ -16,19 +17,16 @@ import {
PIVOT_SUPPORTED_AGGS,
PIVOT_SUPPORTED_GROUP_BY_AGGS,
} from '../../../../common';
+import { SearchItems } from '../../../../hooks/use_search_items';
import { PivotPreview } from './pivot_preview';
-// workaround to make React.memo() work with enzyme
-jest.mock('react', () => {
- const r = jest.requireActual('react');
- return { ...r, memo: (x: any) => x };
-});
-
+jest.mock('ui/new_platform');
jest.mock('../../../../../shared_imports');
describe('Transform: element because shallow() would fail
- // with the Provider being the outer most component.
- const wrapper = shallow(
-
+
+
);
- expect(wrapper).toMatchSnapshot();
+ // Act
+ // Assert
+ expect(getByText('Transform pivot preview')).toBeInTheDocument();
});
});
diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/pivot_preview.tsx b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/pivot_preview.tsx
index b755956eae24e..9b32bbbae839e 100644
--- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/pivot_preview.tsx
+++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/pivot_preview.tsx
@@ -24,8 +24,6 @@ import {
import { dictionaryToArray } from '../../../../../../common/types/common';
import { getNestedProperty } from '../../../../../../common/utils/object_utils';
-import { useCurrentIndexPattern } from '../../../../lib/kibana';
-
import {
euiDataGridStyle,
euiDataGridToolbarSettings,
@@ -36,6 +34,7 @@ import {
PivotGroupByConfigDict,
PivotQuery,
} from '../../../../common';
+import { SearchItems } from '../../../../hooks/use_search_items';
import { getPivotPreviewDevConsoleStatement, multiColumnSortFactory } from './common';
import { PIVOT_PREVIEW_STATUS, usePivotPreviewData } from './use_pivot_preview_data';
@@ -103,184 +102,186 @@ const ErrorMessage: FC = ({ message }) => (
interface PivotPreviewProps {
aggs: PivotAggsConfigDict;
groupBy: PivotGroupByConfigDict;
+ indexPattern: SearchItems['indexPattern'];
query: PivotQuery;
}
const defaultPagination = { pageIndex: 0, pageSize: 5 };
-export const PivotPreview: FC = React.memo(({ aggs, groupBy, query }) => {
- const indexPattern = useCurrentIndexPattern();
-
- const {
- previewData: data,
- previewMappings,
- errorMessage,
- previewRequest,
- status,
- } = usePivotPreviewData(indexPattern, query, aggs, groupBy);
- const groupByArr = dictionaryToArray(groupBy);
-
- // Filters mapping properties of type `object`, which get returned for nested field parents.
- const columnKeys = Object.keys(previewMappings.properties).filter(
- key => previewMappings.properties[key].type !== 'object'
- );
- columnKeys.sort(sortColumns(groupByArr));
-
- // Column visibility
- const [visibleColumns, setVisibleColumns] = useState(columnKeys);
-
- useEffect(() => {
- setVisibleColumns(columnKeys);
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [JSON.stringify(columnKeys)]);
-
- const [pagination, setPagination] = useState(defaultPagination);
-
- // Reset pagination if data changes. This is to avoid ending up with an empty table
- // when for example the user selected a page that is not available with the updated data.
- useEffect(() => {
- setPagination(defaultPagination);
- }, [data.length]);
-
- // EuiDataGrid State
- const dataGridColumns = columnKeys.map(id => ({ id }));
-
- const onChangeItemsPerPage = useCallback(
- pageSize => {
- setPagination(p => {
- const pageIndex = Math.floor((p.pageSize * p.pageIndex) / pageSize);
- return { pageIndex, pageSize };
- });
- },
- [setPagination]
- );
+export const PivotPreview: FC = React.memo(
+ ({ aggs, groupBy, indexPattern, query }) => {
+ const {
+ previewData: data,
+ previewMappings,
+ errorMessage,
+ previewRequest,
+ status,
+ } = usePivotPreviewData(indexPattern, query, aggs, groupBy);
+ const groupByArr = dictionaryToArray(groupBy);
+
+ // Filters mapping properties of type `object`, which get returned for nested field parents.
+ const columnKeys = Object.keys(previewMappings.properties).filter(
+ key => previewMappings.properties[key].type !== 'object'
+ );
+ columnKeys.sort(sortColumns(groupByArr));
+
+ // Column visibility
+ const [visibleColumns, setVisibleColumns] = useState(columnKeys);
+
+ useEffect(() => {
+ setVisibleColumns(columnKeys);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [JSON.stringify(columnKeys)]);
+
+ const [pagination, setPagination] = useState(defaultPagination);
+
+ // Reset pagination if data changes. This is to avoid ending up with an empty table
+ // when for example the user selected a page that is not available with the updated data.
+ useEffect(() => {
+ setPagination(defaultPagination);
+ }, [data.length]);
+
+ // EuiDataGrid State
+ const dataGridColumns = columnKeys.map(id => ({ id }));
+
+ const onChangeItemsPerPage = useCallback(
+ pageSize => {
+ setPagination(p => {
+ const pageIndex = Math.floor((p.pageSize * p.pageIndex) / pageSize);
+ return { pageIndex, pageSize };
+ });
+ },
+ [setPagination]
+ );
- const onChangePage = useCallback(pageIndex => setPagination(p => ({ ...p, pageIndex })), [
- setPagination,
- ]);
+ const onChangePage = useCallback(pageIndex => setPagination(p => ({ ...p, pageIndex })), [
+ setPagination,
+ ]);
- // Sorting config
- const [sortingColumns, setSortingColumns] = useState([]);
- const onSort = useCallback(sc => setSortingColumns(sc), [setSortingColumns]);
+ // Sorting config
+ const [sortingColumns, setSortingColumns] = useState([]);
+ const onSort = useCallback(sc => setSortingColumns(sc), [setSortingColumns]);
- if (sortingColumns.length > 0) {
- data.sort(multiColumnSortFactory(sortingColumns));
- }
+ if (sortingColumns.length > 0) {
+ data.sort(multiColumnSortFactory(sortingColumns));
+ }
- const pageData = data.slice(
- pagination.pageIndex * pagination.pageSize,
- (pagination.pageIndex + 1) * pagination.pageSize
- );
+ const pageData = data.slice(
+ pagination.pageIndex * pagination.pageSize,
+ (pagination.pageIndex + 1) * pagination.pageSize
+ );
- const renderCellValue = useMemo(() => {
- return ({
- rowIndex,
- columnId,
- setCellProps,
- }: {
- rowIndex: number;
- columnId: string;
- setCellProps: any;
- }) => {
- const adjustedRowIndex = rowIndex - pagination.pageIndex * pagination.pageSize;
-
- const cellValue = pageData.hasOwnProperty(adjustedRowIndex)
- ? getNestedProperty(pageData[adjustedRowIndex], columnId, null)
- : null;
-
- if (typeof cellValue === 'object' && cellValue !== null) {
- return JSON.stringify(cellValue);
- }
+ const renderCellValue = useMemo(() => {
+ return ({
+ rowIndex,
+ columnId,
+ setCellProps,
+ }: {
+ rowIndex: number;
+ columnId: string;
+ setCellProps: any;
+ }) => {
+ const adjustedRowIndex = rowIndex - pagination.pageIndex * pagination.pageSize;
+
+ const cellValue = pageData.hasOwnProperty(adjustedRowIndex)
+ ? getNestedProperty(pageData[adjustedRowIndex], columnId, null)
+ : null;
+
+ if (typeof cellValue === 'object' && cellValue !== null) {
+ return JSON.stringify(cellValue);
+ }
- if (cellValue === undefined) {
- return null;
- }
+ if (cellValue === undefined) {
+ return null;
+ }
- return cellValue;
- };
- }, [pageData, pagination.pageIndex, pagination.pageSize]);
+ return cellValue;
+ };
+ }, [pageData, pagination.pageIndex, pagination.pageSize]);
+
+ if (status === PIVOT_PREVIEW_STATUS.ERROR) {
+ return (
+
-
-
-
-
+ const Providers = getAppProviders(createPublicShim());
+ const { getByText } = render(
+
+
+
+
+
+
+ );
+ }
- if (status === PIVOT_PREVIEW_STATUS.ERROR) {
- return (
-
-
-
-
-
-
- );
- }
+ if (data.length === 0) {
+ let noDataMessage = i18n.translate(
+ 'xpack.transform.pivotPreview.PivotPreviewNoDataCalloutBody',
+ {
+ defaultMessage:
+ 'The preview request did not return any data. Please ensure the optional query returns data and that values exist for the field used by group-by and aggregation fields.',
+ }
+ );
- if (data.length === 0) {
- let noDataMessage = i18n.translate(
- 'xpack.transform.pivotPreview.PivotPreviewNoDataCalloutBody',
- {
- defaultMessage:
- 'The preview request did not return any data. Please ensure the optional query returns data and that values exist for the field used by group-by and aggregation fields.',
+ const aggsArr = dictionaryToArray(aggs);
+ if (aggsArr.length === 0 || groupByArr.length === 0) {
+ noDataMessage = i18n.translate(
+ 'xpack.transform.pivotPreview.PivotPreviewIncompleteConfigCalloutBody',
+ {
+ defaultMessage: 'Please choose at least one group-by field and aggregation.',
+ }
+ );
}
- );
- const aggsArr = dictionaryToArray(aggs);
- if (aggsArr.length === 0 || groupByArr.length === 0) {
- noDataMessage = i18n.translate(
- 'xpack.transform.pivotPreview.PivotPreviewIncompleteConfigCalloutBody',
- {
- defaultMessage: 'Please choose at least one group-by field and aggregation.',
- }
+ return (
+
+
+
+
+
);
}
+
+ if (columnKeys.length === 0) {
+ return null;
+ }
+
return (
- {noDataMessage}
+
+
-
-
+
+ )}
);
}
-
- if (columnKeys.length === 0) {
- return null;
- }
-
- return (
- ', () => {
test('Minimal initialization', () => {
- // Using a wrapping
{noDataMessage}
-
+ {status === PIVOT_PREVIEW_STATUS.LOADING && }
+ {status !== PIVOT_PREVIEW_STATUS.LOADING && (
+
+ )}
+
+ {dataGridColumns.length > 0 && data.length > 0 && (
+
-
-
- )}
-
- );
-});
+);
diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.test.tsx b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.test.tsx
index 44edd1340e8d6..f45ef7cfddbf9 100644
--- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.test.tsx
+++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.test.tsx
@@ -4,40 +4,44 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { shallow } from 'enzyme';
import React from 'react';
+import { render } from '@testing-library/react';
+import '@testing-library/jest-dom/extend-expect';
-import { KibanaContext } from '../../../../lib/kibana';
-
+import { createPublicShim } from '../../../../../shim';
+import { getAppProviders } from '../../../../app_dependencies';
import {
PivotAggsConfigDict,
PivotGroupByConfigDict,
PIVOT_SUPPORTED_AGGS,
PIVOT_SUPPORTED_GROUP_BY_AGGS,
} from '../../../../common';
-import { StepDefineForm, getAggNameConflictToastMessages } from './step_define_form';
+import { SearchItems } from '../../../../hooks/use_search_items';
-// workaround to make React.memo() work with enzyme
-jest.mock('react', () => {
- const r = jest.requireActual('react');
- return { ...r, memo: (x: any) => x };
-});
+import { StepDefineForm, getAggNameConflictToastMessages } from './step_define_form';
+jest.mock('ui/new_platform');
jest.mock('../../../../../shared_imports');
describe('Transform:
- {status === PIVOT_PREVIEW_STATUS.LOADING && }
- {status !== PIVOT_PREVIEW_STATUS.LOADING && (
-
- )}
-
- {dataGridColumns.length > 0 && data.length > 0 && (
- element because shallow() would fail
- // with the Provider being the outer most component.
- const wrapper = shallow(
-
+
+
);
- expect(wrapper).toMatchSnapshot();
+ // Act
+ // Assert
+ expect(getByLabelText('Index pattern')).toBeInTheDocument();
});
});
diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx
index 9b96e4b1ee758..f61f54c38680e 100644
--- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx
+++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx
@@ -26,6 +26,7 @@ import {
EuiSwitch,
} from '@elastic/eui';
+import { SavedSearchQuery, SearchItems } from '../../../../hooks/use_search_items';
import { useXJsonMode, xJsonMode } from '../../../../hooks/use_x_json_mode';
import { useDocumentationLinks, useToastNotifications } from '../../../../app_dependencies';
import { TransformPivotConfig } from '../../../../common';
@@ -38,12 +39,6 @@ import { PivotPreview } from './pivot_preview';
import { KqlFilterBar } from '../../../../../shared_imports';
import { SwitchModal } from './switch_modal';
-import {
- useKibanaContext,
- InitializedKibanaContextValue,
- SavedSearchQuery,
-} from '../../../../lib/kibana';
-
import {
getPivotQuery,
getPreviewRequestBody,
@@ -78,18 +73,14 @@ export interface StepDefineExposedState {
const defaultSearch = '*';
const emptySearch = '';
-export function getDefaultStepDefineState(
- kibanaContext: InitializedKibanaContextValue
-): StepDefineExposedState {
+export function getDefaultStepDefineState(searchItems: SearchItems): StepDefineExposedState {
return {
aggList: {} as PivotAggsConfigDict,
groupByList: {} as PivotGroupByConfigDict,
isAdvancedPivotEditorEnabled: false,
isAdvancedSourceEditorEnabled: false,
- searchString:
- kibanaContext.currentSavedSearch !== undefined ? kibanaContext.combinedQuery : defaultSearch,
- searchQuery:
- kibanaContext.currentSavedSearch !== undefined ? kibanaContext.combinedQuery : defaultSearch,
+ searchString: searchItems.savedSearch !== undefined ? searchItems.combinedQuery : defaultSearch,
+ searchQuery: searchItems.savedSearch !== undefined ? searchItems.combinedQuery : defaultSearch,
sourceConfigUpdated: false,
valid: false,
};
@@ -242,14 +233,14 @@ export function getAggNameConflictToastMessages(
interface Props {
overrides?: StepDefineExposedState;
onChange(s: StepDefineExposedState): void;
+ searchItems: SearchItems;
}
-export const StepDefineForm: FC = React.memo(({ overrides = {}, onChange }) => {
- const kibanaContext = useKibanaContext();
+export const StepDefineForm: FC = React.memo(({ overrides = {}, onChange, searchItems }) => {
const toastNotifications = useToastNotifications();
const { esQueryDsl, esTransformPivot } = useDocumentationLinks();
- const defaults = { ...getDefaultStepDefineState(kibanaContext), ...overrides };
+ const defaults = { ...getDefaultStepDefineState(searchItems), ...overrides };
// The search filter
const [searchString, setSearchString] = useState(defaults.searchString);
@@ -267,7 +258,7 @@ export const StepDefineForm: FC = React.memo(({ overrides = {}, onChange
// The list of selected group by fields
const [groupByList, setGroupByList] = useState(defaults.groupByList);
- const indexPattern = kibanaContext.currentIndexPattern;
+ const { indexPattern } = searchItems;
const {
groupByOptions,
@@ -568,7 +559,7 @@ export const StepDefineForm: FC = React.memo(({ overrides = {}, onChange
- {kibanaContext.currentSavedSearch === undefined && typeof searchString === 'string' && (
+ {searchItems.savedSearch === undefined && typeof searchString === 'string' && (
= React.memo(({ overrides = {}, onChange
)}
- {kibanaContext.currentSavedSearch === undefined && (
+ {searchItems.savedSearch === undefined && (
@@ -720,16 +711,15 @@ export const StepDefineForm: FC = React.memo(({ overrides = {}, onChange
)}
- {kibanaContext.currentSavedSearch !== undefined &&
- kibanaContext.currentSavedSearch.id !== undefined && (
-
- {kibanaContext.currentSavedSearch.title}
-
- )}
+ {searchItems.savedSearch !== undefined && searchItems.savedSearch.id !== undefined && (
+
+ {searchItems.savedSearch.title}
+
+ )}
{!isAdvancedPivotEditorEnabled && (
@@ -903,9 +893,14 @@ export const StepDefineForm: FC = React.memo(({ overrides = {}, onChange
-
+
-
+
);
diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_summary.test.tsx b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_summary.test.tsx
index 78f6fc30f9191..0f7da50bbbade 100644
--- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_summary.test.tsx
+++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_summary.test.tsx
@@ -4,30 +4,35 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { shallow } from 'enzyme';
import React from 'react';
+import { render } from '@testing-library/react';
+import '@testing-library/jest-dom/extend-expect';
-import { KibanaContext } from '../../../../lib/kibana';
-
+import { createPublicShim } from '../../../../../shim';
+import { getAppProviders } from '../../../../app_dependencies';
import {
PivotAggsConfig,
PivotGroupByConfig,
PIVOT_SUPPORTED_AGGS,
PIVOT_SUPPORTED_GROUP_BY_AGGS,
} from '../../../../common';
+import { SearchItems } from '../../../../hooks/use_search_items';
+
import { StepDefineExposedState } from './step_define_form';
import { StepDefineSummary } from './step_define_summary';
-// workaround to make React.memo() work with enzyme
-jest.mock('react', () => {
- const r = jest.requireActual('react');
- return { ...r, memo: (x: any) => x };
-});
-
+jest.mock('ui/new_platform');
jest.mock('../../../../../shared_imports');
describe('Transform: ', () => {
test('Minimal initialization', () => {
+ // Arrange
+ const searchItems = {
+ indexPattern: {
+ title: 'the-index-pattern-title',
+ fields: [] as any[],
+ } as SearchItems['indexPattern'],
+ };
const groupBy: PivotGroupByConfig = {
agg: PIVOT_SUPPORTED_GROUP_BY_AGGS.TERMS,
field: 'the-group-by-field',
@@ -40,7 +45,7 @@ describe('Transform: ', () => {
aggName: 'the-group-by-agg-name',
dropDownName: 'the-group-by-drop-down-name',
};
- const props: StepDefineExposedState = {
+ const formState: StepDefineExposedState = {
aggList: { 'the-agg-name': agg },
groupByList: { 'the-group-by-name': groupBy },
isAdvancedPivotEditorEnabled: false,
@@ -51,16 +56,16 @@ describe('Transform: ', () => {
valid: true,
};
- // Using a wrapping
-
- {}} />
-
-
+ // Arrange
+ const searchItems = {
+ indexPattern: {
+ title: 'the-index-pattern-title',
+ fields: [] as any[],
+ } as SearchItems['indexPattern'],
+ };
+ const Providers = getAppProviders(createPublicShim());
+ const { getByLabelText } = render(
+ element because shallow() would fail
- // with the Provider being the outer most component.
- const wrapper = shallow(
-
+
+
);
- expect(wrapper).toMatchSnapshot();
+ // Act
+ // Assert
+ expect(getByText('Group by')).toBeInTheDocument();
+ expect(getByText('Aggregations')).toBeInTheDocument();
});
});
diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_summary.tsx b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_summary.tsx
index 30c447f62c760..f8fb9db9bd686 100644
--- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_summary.tsx
+++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_summary.tsx
@@ -17,26 +17,27 @@ import {
EuiText,
} from '@elastic/eui';
-import { useKibanaContext } from '../../../../lib/kibana';
+import { getPivotQuery } from '../../../../common';
+import { SearchItems } from '../../../../hooks/use_search_items';
import { AggListSummary } from '../aggregation_list';
import { GroupByListSummary } from '../group_by_list';
-import { PivotPreview } from './pivot_preview';
-import { getPivotQuery } from '../../../../common';
+import { PivotPreview } from './pivot_preview';
import { StepDefineExposedState } from './step_define_form';
const defaultSearch = '*';
const emptySearch = '';
-export const StepDefineSummary: FC = ({
- searchString,
- searchQuery,
- groupByList,
- aggList,
-}) => {
- const kibanaContext = useKibanaContext();
+interface Props {
+ formState: StepDefineExposedState;
+ searchItems: SearchItems;
+}
+export const StepDefineSummary: FC = ({
+ formState: { searchString, searchQuery, groupByList, aggList },
+ searchItems,
+}) => {
const pivotQuery = getPivotQuery(searchQuery);
let useCodeBlock = false;
let displaySearch;
@@ -55,8 +56,8 @@ export const StepDefineSummary: FC = ({
- {kibanaContext.currentSavedSearch !== undefined &&
- kibanaContext.currentSavedSearch.id === undefined &&
+ {searchItems.savedSearch !== undefined &&
+ searchItems.savedSearch.id === undefined &&
typeof searchString === 'string' && (
= ({
defaultMessage: 'Index pattern',
})}
>
- {kibanaContext.currentIndexPattern.title}
+ {searchItems.indexPattern.title}
{useCodeBlock === false && displaySearch !== emptySearch && (
= ({
)}
- {kibanaContext.currentSavedSearch !== undefined &&
- kibanaContext.currentSavedSearch.id !== undefined && (
-
- {kibanaContext.currentSavedSearch.title}
-
- )}
+ {searchItems.savedSearch !== undefined && searchItems.savedSearch.id !== undefined && (
+
+ {searchItems.savedSearch.title}
+
+ )}
= ({
-
+
diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx
index 5ae2180bfe779..ea9483af49302 100644
--- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx
+++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx
@@ -11,11 +11,15 @@ import { i18n } from '@kbn/i18n';
import { EuiLink, EuiSwitch, EuiFieldText, EuiForm, EuiFormRow, EuiSelect } from '@elastic/eui';
import { toMountPoint } from '../../../../../../../../../../src/plugins/kibana_react/public';
-import { useKibanaContext } from '../../../../lib/kibana';
import { isValidIndexName } from '../../../../../../common/utils/es_utils';
-import { useDocumentationLinks, useToastNotifications } from '../../../../app_dependencies';
+import {
+ useAppDependencies,
+ useDocumentationLinks,
+ useToastNotifications,
+} from '../../../../app_dependencies';
import { ToastNotificationText } from '../../../../components';
+import { SearchItems } from '../../../../hooks/use_search_items';
import { useApi } from '../../../../hooks/use_api';
import { isTransformIdValid, TransformId, TransformPivotConfig } from '../../../../common';
@@ -67,109 +71,129 @@ export function applyTransformConfigToDetailsState(
interface Props {
overrides?: StepDetailsExposedState;
onChange(s: StepDetailsExposedState): void;
+ searchItems: SearchItems;
}
-export const StepDetailsForm: FC = React.memo(({ overrides = {}, onChange }) => {
- const kibanaContext = useKibanaContext();
- const toastNotifications = useToastNotifications();
- const { esIndicesCreateIndex } = useDocumentationLinks();
+export const StepDetailsForm: FC = React.memo(
+ ({ overrides = {}, onChange, searchItems }) => {
+ const deps = useAppDependencies();
+ const toastNotifications = useToastNotifications();
+ const { esIndicesCreateIndex } = useDocumentationLinks();
- const defaults = { ...getDefaultStepDetailsState(), ...overrides };
+ const defaults = { ...getDefaultStepDetailsState(), ...overrides };
- const [transformId, setTransformId] = useState(defaults.transformId);
- const [transformDescription, setTransformDescription] = useState(
- defaults.transformDescription
- );
- const [destinationIndex, setDestinationIndex] = useState(defaults.destinationIndex);
- const [transformIds, setTransformIds] = useState([]);
- const [indexNames, setIndexNames] = useState([]);
- const [indexPatternTitles, setIndexPatternTitles] = useState([]);
- const [createIndexPattern, setCreateIndexPattern] = useState(defaults.createIndexPattern);
+ const [transformId, setTransformId] = useState(defaults.transformId);
+ const [transformDescription, setTransformDescription] = useState(
+ defaults.transformDescription
+ );
+ const [destinationIndex, setDestinationIndex] = useState(
+ defaults.destinationIndex
+ );
+ const [transformIds, setTransformIds] = useState([]);
+ const [indexNames, setIndexNames] = useState([]);
+ const [indexPatternTitles, setIndexPatternTitles] = useState([]);
+ const [createIndexPattern, setCreateIndexPattern] = useState(defaults.createIndexPattern);
- // Continuous mode state
- const [isContinuousModeEnabled, setContinuousModeEnabled] = useState(
- defaults.isContinuousModeEnabled
- );
+ // Continuous mode state
+ const [isContinuousModeEnabled, setContinuousModeEnabled] = useState(
+ defaults.isContinuousModeEnabled
+ );
- const api = useApi();
+ const api = useApi();
- // fetch existing transform IDs and indices once for form validation
- useEffect(() => {
- // use an IIFE to avoid returning a Promise to useEffect.
- (async function() {
- try {
- setTransformIds(
- (await api.getTransforms()).transforms.map(
- (transform: TransformPivotConfig) => transform.id
- )
- );
- } catch (e) {
- toastNotifications.addDanger({
- title: i18n.translate('xpack.transform.stepDetailsForm.errorGettingTransformList', {
- defaultMessage: 'An error occurred getting the existing transform IDs:',
- }),
- text: toMountPoint( ),
- });
- }
+ // fetch existing transform IDs and indices once for form validation
+ useEffect(() => {
+ // use an IIFE to avoid returning a Promise to useEffect.
+ (async function() {
+ try {
+ setTransformIds(
+ (await api.getTransforms()).transforms.map(
+ (transform: TransformPivotConfig) => transform.id
+ )
+ );
+ } catch (e) {
+ toastNotifications.addDanger({
+ title: i18n.translate('xpack.transform.stepDetailsForm.errorGettingTransformList', {
+ defaultMessage: 'An error occurred getting the existing transform IDs:',
+ }),
+ text: toMountPoint( ),
+ });
+ }
- try {
- setIndexNames((await api.getIndices()).map(index => index.name));
- } catch (e) {
- toastNotifications.addDanger({
- title: i18n.translate('xpack.transform.stepDetailsForm.errorGettingIndexNames', {
- defaultMessage: 'An error occurred getting the existing index names:',
- }),
- text: toMountPoint( ),
- });
- }
+ try {
+ setIndexNames((await api.getIndices()).map(index => index.name));
+ } catch (e) {
+ toastNotifications.addDanger({
+ title: i18n.translate('xpack.transform.stepDetailsForm.errorGettingIndexNames', {
+ defaultMessage: 'An error occurred getting the existing index names:',
+ }),
+ text: toMountPoint( ),
+ });
+ }
- try {
- setIndexPatternTitles(await kibanaContext.indexPatterns.getTitles());
- } catch (e) {
- toastNotifications.addDanger({
- title: i18n.translate('xpack.transform.stepDetailsForm.errorGettingIndexPatternTitles', {
- defaultMessage: 'An error occurred getting the existing index pattern titles:',
- }),
- text: toMountPoint( ),
- });
- }
- })();
- // custom comparison
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [kibanaContext.initialized]);
+ try {
+ setIndexPatternTitles(await deps.plugins.data.indexPatterns.getTitles());
+ } catch (e) {
+ toastNotifications.addDanger({
+ title: i18n.translate(
+ 'xpack.transform.stepDetailsForm.errorGettingIndexPatternTitles',
+ {
+ defaultMessage: 'An error occurred getting the existing index pattern titles:',
+ }
+ ),
+ text: toMountPoint( ),
+ });
+ }
+ })();
+ // run once
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
- const dateFieldNames = kibanaContext.currentIndexPattern.fields
- .filter(f => f.type === 'date')
- .map(f => f.name)
- .sort();
- const isContinuousModeAvailable = dateFieldNames.length > 0;
- const [continuousModeDateField, setContinuousModeDateField] = useState(
- isContinuousModeAvailable ? dateFieldNames[0] : ''
- );
- const [continuousModeDelay, setContinuousModeDelay] = useState(defaults.continuousModeDelay);
- const isContinuousModeDelayValid = delayValidator(continuousModeDelay);
+ const dateFieldNames = searchItems.indexPattern.fields
+ .filter(f => f.type === 'date')
+ .map(f => f.name)
+ .sort();
+ const isContinuousModeAvailable = dateFieldNames.length > 0;
+ const [continuousModeDateField, setContinuousModeDateField] = useState(
+ isContinuousModeAvailable ? dateFieldNames[0] : ''
+ );
+ const [continuousModeDelay, setContinuousModeDelay] = useState(defaults.continuousModeDelay);
+ const isContinuousModeDelayValid = delayValidator(continuousModeDelay);
- const transformIdExists = transformIds.some(id => transformId === id);
- const transformIdEmpty = transformId === '';
- const transformIdValid = isTransformIdValid(transformId);
+ const transformIdExists = transformIds.some(id => transformId === id);
+ const transformIdEmpty = transformId === '';
+ const transformIdValid = isTransformIdValid(transformId);
- const indexNameExists = indexNames.some(name => destinationIndex === name);
- const indexNameEmpty = destinationIndex === '';
- const indexNameValid = isValidIndexName(destinationIndex);
- const indexPatternTitleExists = indexPatternTitles.some(name => destinationIndex === name);
+ const indexNameExists = indexNames.some(name => destinationIndex === name);
+ const indexNameEmpty = destinationIndex === '';
+ const indexNameValid = isValidIndexName(destinationIndex);
+ const indexPatternTitleExists = indexPatternTitles.some(name => destinationIndex === name);
- const valid =
- !transformIdEmpty &&
- transformIdValid &&
- !transformIdExists &&
- !indexNameEmpty &&
- indexNameValid &&
- (!indexPatternTitleExists || !createIndexPattern) &&
- (!isContinuousModeAvailable || (isContinuousModeAvailable && isContinuousModeDelayValid));
+ const valid =
+ !transformIdEmpty &&
+ transformIdValid &&
+ !transformIdExists &&
+ !indexNameEmpty &&
+ indexNameValid &&
+ (!indexPatternTitleExists || !createIndexPattern) &&
+ (!isContinuousModeAvailable || (isContinuousModeAvailable && isContinuousModeDelayValid));
- // expose state to wizard
- useEffect(() => {
- onChange({
+ // expose state to wizard
+ useEffect(() => {
+ onChange({
+ continuousModeDateField,
+ continuousModeDelay,
+ createIndexPattern,
+ isContinuousModeEnabled,
+ transformId,
+ transformDescription,
+ destinationIndex,
+ touched: true,
+ valid,
+ });
+ // custom comparison
+ /* eslint-disable react-hooks/exhaustive-deps */
+ }, [
continuousModeDateField,
continuousModeDelay,
createIndexPattern,
@@ -177,232 +201,223 @@ export const StepDetailsForm: FC = React.memo(({ overrides = {}, onChange
transformId,
transformDescription,
destinationIndex,
- touched: true,
valid,
- });
- // custom comparison
- /* eslint-disable react-hooks/exhaustive-deps */
- }, [
- continuousModeDateField,
- continuousModeDelay,
- createIndexPattern,
- isContinuousModeEnabled,
- transformId,
- transformDescription,
- destinationIndex,
- valid,
- /* eslint-enable react-hooks/exhaustive-deps */
- ]);
+ /* eslint-enable react-hooks/exhaustive-deps */
+ ]);
- return (
- >;
setStepDefineState: React.Dispatch>;
+ searchItems: SearchItems;
}
const StepDefine: FC = ({
@@ -53,6 +53,7 @@ const StepDefine: FC = ({
stepDefineState,
setCurrentStep,
setStepDefineState,
+ searchItems,
}) => {
const definePivotRef = useRef(null);
@@ -61,31 +62,36 @@ const StepDefine: FC = ({
{isCurrentStep && (
-
+
setCurrentStep(WIZARD_STEPS.DETAILS)}
nextActive={stepDefineState.valid}
/>
)}
- {!isCurrentStep && }
+ {!isCurrentStep && (
+
+ )}
);
};
interface WizardProps {
cloneConfig?: TransformPivotConfig;
+ searchItems: SearchItems;
}
-export const Wizard: FC = React.memo(({ cloneConfig }) => {
- const kibanaContext = useKibanaContext();
-
+export const Wizard: FC = React.memo(({ cloneConfig, searchItems }) => {
// The current WIZARD_STEP
const [currentStep, setCurrentStep] = useState(WIZARD_STEPS.DEFINE);
// The DEFINE state
const [stepDefineState, setStepDefineState] = useState(
- applyTransformConfigToDefineState(getDefaultStepDefineState(kibanaContext), cloneConfig)
+ applyTransformConfigToDefineState(getDefaultStepDefineState(searchItems), cloneConfig)
);
// The DETAILS state
@@ -95,7 +101,11 @@ export const Wizard: FC = React.memo(({ cloneConfig }) => {
const stepDetails =
currentStep === WIZARD_STEPS.DETAILS ? (
-
+
) : (
);
@@ -122,7 +132,7 @@ export const Wizard: FC = React.memo(({ cloneConfig }) => {
}
}, []);
- const indexPattern = kibanaContext.currentIndexPattern;
+ const { indexPattern } = searchItems;
const transformConfig = getCreateRequestBody(
indexPattern.title,
@@ -154,6 +164,7 @@ export const Wizard: FC = React.memo(({ cloneConfig }) => {
stepDefineState={stepDefineState}
setCurrentStep={setCurrentStep}
setStepDefineState={setStepDefineState}
+ searchItems={searchItems}
/>
),
},
diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/create_transform_section.tsx b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/create_transform_section.tsx
index 5196f281adf0a..d09fc0913590e 100644
--- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/create_transform_section.tsx
+++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/create_transform_section.tsx
@@ -22,9 +22,9 @@ import {
import { APP_CREATE_TRANSFORM_CLUSTER_PRIVILEGES } from '../../../../common/constants';
import { useDocumentationLinks } from '../../app_dependencies';
+import { useSearchItems } from '../../hooks/use_search_items';
import { breadcrumbService, docTitleService, BREADCRUMB_SECTION } from '../../services/navigation';
import { PrivilegesWrapper } from '../../lib/authorization';
-import { KibanaProvider, RenderOnlyWithInitializedKibanaContext } from '../../lib/kibana';
import { Wizard } from './components/wizard';
@@ -38,43 +38,41 @@ export const CreateTransformSection: FC = ({ match }) => {
const { esTransform } = useDocumentationLinks();
+ const { searchItems } = useSearchItems(match.params.savedObjectId);
+
return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {searchItems !== undefined && }
+
+
);
};
diff --git a/x-pack/legacy/plugins/transform/public/plugin.ts b/x-pack/legacy/plugins/transform/public/plugin.ts
index 23fad00fb0786..7b5fbbb4a2151 100644
--- a/x-pack/legacy/plugins/transform/public/plugin.ts
+++ b/x-pack/legacy/plugins/transform/public/plugin.ts
@@ -11,7 +11,6 @@ import { breadcrumbService } from './app/services/navigation';
import { docTitleService } from './app/services/navigation';
import { textService } from './app/services/text';
import { uiMetricService } from './app/services/ui_metric';
-import { createSavedSearchesLoader } from '../../../../../src/plugins/discover/public';
export class Plugin {
public start(core: ShimCore, plugins: ShimPlugins): void {
@@ -27,7 +26,7 @@ export class Plugin {
savedObjects,
overlays,
} = core;
- const { data, management, savedSearches: coreSavedSearches, uiMetric, xsrfToken } = plugins;
+ const { data, management, uiMetric, xsrfToken } = plugins;
// AppCore/AppPlugins to be passed on as React context
const appDependencies = {
@@ -46,7 +45,6 @@ export class Plugin {
plugins: {
data,
management,
- savedSearches: coreSavedSearches,
xsrfToken,
},
};
@@ -61,14 +59,6 @@ export class Plugin {
}),
order: 3,
mount(params) {
- const savedSearches = createSavedSearchesLoader({
- savedObjectsClient: core.savedObjects.client,
- indexPatterns: plugins.data.indexPatterns,
- chrome: core.chrome,
- overlays: core.overlays,
- });
- coreSavedSearches.setClient(savedSearches);
-
breadcrumbService.setup(params.setBreadcrumbs);
params.setBreadcrumbs([
{
diff --git a/x-pack/legacy/plugins/transform/public/shared_imports.ts b/x-pack/legacy/plugins/transform/public/shared_imports.ts
index b077cd8836c4b..1ca71f8c4aa77 100644
--- a/x-pack/legacy/plugins/transform/public/shared_imports.ts
+++ b/x-pack/legacy/plugins/transform/public/shared_imports.ts
@@ -4,6 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
+export { createSavedSearchesLoader } from '../../../../../src/plugins/discover/public';
export { XJsonMode } from '../../../../plugins/es_ui_shared/console_lang/ace/modes/x_json';
export {
collapseLiteralStrings,
diff --git a/x-pack/legacy/plugins/transform/public/shim.ts b/x-pack/legacy/plugins/transform/public/shim.ts
index 05f7626e25e9d..9941aabcf3255 100644
--- a/x-pack/legacy/plugins/transform/public/shim.ts
+++ b/x-pack/legacy/plugins/transform/public/shim.ts
@@ -13,7 +13,6 @@ import { docTitle } from 'ui/doc_title/doc_title';
import { createUiStatsReporter } from '../../../../../src/legacy/core_plugins/ui_metric/public';
import { TRANSFORM_DOC_PATHS } from './app/constants';
-import { SavedSearchLoader } from '../../../../../src/plugins/discover/public';
export type NpCore = typeof npStart.core;
export type NpPlugins = typeof npStart.plugins;
@@ -33,7 +32,7 @@ export type AppCore = Pick<
| 'overlays'
| 'notifications'
>;
-export type AppPlugins = Pick;
+export type AppPlugins = Pick;
export interface AppDependencies {
core: AppCore;
@@ -61,18 +60,10 @@ export interface ShimPlugins extends NpPlugins {
uiMetric: {
createUiStatsReporter: typeof createUiStatsReporter;
};
- savedSearches: {
- getClient(): any;
- setClient(client: any): void;
- };
xsrfToken: string;
}
export function createPublicShim(): { core: ShimCore; plugins: ShimPlugins } {
- // This is an Angular service, which is why we use this provider pattern
- // to access it within our React app.
- let savedSearches: SavedSearchLoader;
-
const { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } = npStart.core.docLinks;
return {
@@ -94,12 +85,6 @@ export function createPublicShim(): { core: ShimCore; plugins: ShimPlugins } {
},
plugins: {
...npStart.plugins,
- savedSearches: {
- setClient: (client: any): void => {
- savedSearches = client;
- },
- getClient: (): any => savedSearches,
- },
uiMetric: {
createUiStatsReporter,
},
-
-
-
-
+ const Providers = getAppProviders(createPublicShim());
+ const { getByText } = render(
+
-
-
- setTransformId(e.target.value)}
- aria-label={i18n.translate(
- 'xpack.transform.stepDetailsForm.transformIdInputAriaLabel',
- {
- defaultMessage: 'Choose a unique transform ID.',
- }
- )}
+ return (
+ setContinuousModeDelay(e.target.value)}
+ aria-label={i18n.translate(
+ 'xpack.transform.stepDetailsForm.continuousModeAriaLabel',
+ {
+ defaultMessage: 'Choose a delay.',
+ }
+ )}
+ isInvalid={!isContinuousModeDelayValid}
+ data-test-subj="transformContinuousDelayInput"
+ />
+
+
+ )}
+
+
+ );
+ }
+);
diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/wizard/wizard.tsx b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/wizard/wizard.tsx
index f1861755d9742..0773ecbb1d8d3 100644
--- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/wizard/wizard.tsx
+++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/wizard/wizard.tsx
@@ -10,9 +10,8 @@ import { i18n } from '@kbn/i18n';
import { EuiSteps, EuiStepStatus } from '@elastic/eui';
-import { useKibanaContext } from '../../../../lib/kibana';
-
import { getCreateRequestBody, TransformPivotConfig } from '../../../../common';
+import { SearchItems } from '../../../../hooks/use_search_items';
import {
applyTransformConfigToDefineState,
@@ -46,6 +45,7 @@ interface DefinePivotStepProps {
stepDefineState: StepDefineExposedState;
setCurrentStep: React.Dispatch
+
+
-
-
- setTransformDescription(e.target.value)}
- aria-label={i18n.translate(
- 'xpack.transform.stepDetailsForm.transformDescriptionInputAriaLabel',
- {
- defaultMessage: 'Choose an optional transform description.',
- }
- )}
- data-test-subj="transformDescriptionInput"
- />
-
-
- {i18n.translate('xpack.transform.stepDetailsForm.destinationIndexInvalidError', {
- defaultMessage: 'Invalid destination index name.',
- })}
-
-
- {i18n.translate(
- 'xpack.transform.stepDetailsForm.destinationIndexInvalidErrorLink',
- {
- defaultMessage: 'Learn more about index name limitations.',
- }
- )}
-
- ,
- ]
- }
- >
- setDestinationIndex(e.target.value)}
- aria-label={i18n.translate(
- 'xpack.transform.stepDetailsForm.destinationIndexInputAriaLabel',
+ error={[
+ ...(!transformIdEmpty && !transformIdValid
+ ? [
+ i18n.translate('xpack.transform.stepDetailsForm.transformIdInvalidError', {
+ defaultMessage:
+ 'Must contain lowercase alphanumeric characters (a-z and 0-9), hyphens, and underscores only and must start and end with alphanumeric characters.',
+ }),
+ ]
+ : []),
+ ...(transformIdExists
+ ? [
+ i18n.translate('xpack.transform.stepDetailsForm.transformIdExistsError', {
+ defaultMessage: 'A transform with this ID already exists.',
+ }),
+ ]
+ : []),
+ ]}
+ >
+ setTransformId(e.target.value)}
+ aria-label={i18n.translate(
+ 'xpack.transform.stepDetailsForm.transformIdInputAriaLabel',
+ {
+ defaultMessage: 'Choose a unique transform ID.',
+ }
+ )}
+ isInvalid={(!transformIdEmpty && !transformIdValid) || transformIdExists}
+ data-test-subj="transformIdInput"
+ />
+
+
-
-
- setCreateIndexPattern(!createIndexPattern)}
- data-test-subj="transformCreateIndexPatternSwitch"
- />
-
-
- setContinuousModeEnabled(!isContinuousModeEnabled)}
- disabled={isContinuousModeAvailable === false}
- data-test-subj="transformContinuousModeSwitch"
- />
-
- {isContinuousModeEnabled && (
-
-
+ setTransformDescription(e.target.value)}
+ aria-label={i18n.translate(
+ 'xpack.transform.stepDetailsForm.transformDescriptionInputAriaLabel',
{
- defaultMessage: 'Date field',
+ defaultMessage: 'Choose an optional transform description.',
}
)}
- helpText={i18n.translate(
- 'xpack.transform.stepDetailsForm.continuousModeDateFieldHelpText',
+ data-test-subj="transformDescriptionInput"
+ />
+
+
+ {i18n.translate('xpack.transform.stepDetailsForm.destinationIndexInvalidError', {
+ defaultMessage: 'Invalid destination index name.',
+ })}
+
+
+ {i18n.translate(
+ 'xpack.transform.stepDetailsForm.destinationIndexInvalidErrorLink',
+ {
+ defaultMessage: 'Learn more about index name limitations.',
+ }
+ )}
+
+ ,
+ ]
+ }
+ >
+ setDestinationIndex(e.target.value)}
+ aria-label={i18n.translate(
+ 'xpack.transform.stepDetailsForm.destinationIndexInputAriaLabel',
{
- defaultMessage:
- 'Select the date field that can be used to identify new documents.',
+ defaultMessage: 'Choose a unique destination index name.',
}
)}
- >
- ({ text }))}
- value={continuousModeDateField}
- onChange={e => setContinuousModeDateField(e.target.value)}
- data-test-subj="transformContinuousDateFieldSelect"
- />
-
-
+
+
+
- setContinuousModeDelay(e.target.value)}
- aria-label={i18n.translate(
- 'xpack.transform.stepDetailsForm.continuousModeAriaLabel',
+ checked={createIndexPattern === true}
+ onChange={() => setCreateIndexPattern(!createIndexPattern)}
+ data-test-subj="transformCreateIndexPatternSwitch"
+ />
+
+
+ setContinuousModeEnabled(!isContinuousModeEnabled)}
+ disabled={isContinuousModeAvailable === false}
+ data-test-subj="transformContinuousModeSwitch"
+ />
+
+ {isContinuousModeEnabled && (
+
+
+ ({ text }))}
+ value={continuousModeDateField}
+ onChange={e => setContinuousModeDateField(e.target.value)}
+ data-test-subj="transformContinuousDateFieldSelect"
+ />
+
+
-
-
- )}
-
-
- );
-});
+ error={
+ !isContinuousModeDelayValid && [
+ i18n.translate('xpack.transform.stepDetailsForm.continuousModeDelayError', {
+ defaultMessage: 'Invalid delay format',
+ }),
+ ]
+ }
+ helpText={i18n.translate(
+ 'xpack.transform.stepDetailsForm.continuousModeDelayHelpText',
+ {
+ defaultMessage: 'Time delay between current time and latest input data time.',
+ }
+ )}
+ >
+ -
+