diff --git a/src/legacy/core_plugins/kibana/public/dashboard/listing/dashboard_listing.js b/src/legacy/core_plugins/kibana/public/dashboard/listing/dashboard_listing.js index a8cd8ffcb77f9..d8216361562e2 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/listing/dashboard_listing.js +++ b/src/legacy/core_plugins/kibana/public/dashboard/listing/dashboard_listing.js @@ -19,14 +19,10 @@ import React, { Fragment } from 'react'; import PropTypes from 'prop-types'; -import { injectI18n, FormattedMessage } from '@kbn/i18n/react'; +import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; -import { - EuiLink, - EuiButton, - EuiEmptyPrompt, -} from '@elastic/eui'; +import { EuiLink, EuiButton, EuiEmptyPrompt } from '@elastic/eui'; import { TableListView } from './../../table_list_view'; @@ -37,8 +33,7 @@ export const EMPTY_FILTER = ''; // and not supporting server-side paging. // This component does not try to tackle these problems (yet) and is just feature matching the legacy component // TODO support server side sorting/paging once title and description are sortable on the server. -class DashboardListingUi extends React.Component { - +export class DashboardListing extends React.Component { constructor(props) { super(props); } @@ -54,21 +49,15 @@ class DashboardListingUi extends React.Component { listingLimit={this.props.listingLimit} initialFilter={this.props.initialFilter} noItemsFragment={this.getNoItemsMessage()} - entityName={ - i18n.translate('kbn.dashboard.listing.table.entityName', { - defaultMessage: 'dashboard' - }) - } - entityNamePlural={ - i18n.translate('kbn.dashboard.listing.table.entityNamePlural', { - defaultMessage: 'dashboards' - }) - } - tableListTitle={ - i18n.translate('kbn.dashboard.listing.dashboardsTitle', { - defaultMessage: 'Dashboards' - }) - } + entityName={i18n.translate('kbn.dashboard.listing.table.entityName', { + defaultMessage: 'dashboard', + })} + entityNamePlural={i18n.translate('kbn.dashboard.listing.table.entityNamePlural', { + defaultMessage: 'dashboards', + })} + tableListTitle={i18n.translate('kbn.dashboard.listing.dashboardsTitle', { + defaultMessage: 'Dashboards', + })} /> ); } @@ -146,7 +135,6 @@ class DashboardListingUi extends React.Component { /> ); - } getTableColumns() { @@ -154,7 +142,7 @@ class DashboardListingUi extends React.Component { { field: 'title', name: i18n.translate('kbn.dashboard.listing.table.titleColumnName', { - defaultMessage: 'Title' + defaultMessage: 'Title', }), sortable: true, render: (field, record) => ( @@ -164,22 +152,22 @@ class DashboardListingUi extends React.Component { > {field} - ) + ), }, { field: 'description', name: i18n.translate('kbn.dashboard.listing.table.descriptionColumnName', { - defaultMessage: 'Description' + defaultMessage: 'Description', }), dataType: 'string', sortable: true, - } + }, ]; return tableColumns; } } -DashboardListingUi.propTypes = { +DashboardListing.propTypes = { createItem: PropTypes.func.isRequired, findItems: PropTypes.func.isRequired, deleteItems: PropTypes.func.isRequired, @@ -190,8 +178,6 @@ DashboardListingUi.propTypes = { initialFilter: PropTypes.string, }; -DashboardListingUi.defaultProps = { +DashboardListing.defaultProps = { initialFilter: EMPTY_FILTER, }; - -export const DashboardListing = injectI18n(DashboardListingUi); diff --git a/src/legacy/core_plugins/kibana/public/dashboard/listing/dashboard_listing.test.js b/src/legacy/core_plugins/kibana/public/dashboard/listing/dashboard_listing.test.js index 866cc7300310d..57de395525e1b 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/listing/dashboard_listing.test.js +++ b/src/legacy/core_plugins/kibana/public/dashboard/listing/dashboard_listing.test.js @@ -17,63 +17,54 @@ * under the License. */ -jest.mock('ui/notify', +jest.mock( + 'ui/notify', () => ({ toastNotifications: { addWarning: () => {}, - } - }), { virtual: true }); + }, + }), + { virtual: true } +); -jest.mock('lodash', +jest.mock( + 'lodash', () => ({ ...require.requireActual('lodash'), // mock debounce to fire immediately with no internal timer - debounce: function (func) { + debounce: func => { function debounced(...args) { return func.apply(this, args); } return debounced; - } - }), { virtual: true }); + }, + }), + { virtual: true } +); import React from 'react'; -import { shallowWithIntl } from 'test_utils/enzyme_helpers'; +import { shallow } from 'enzyme'; -import { - DashboardListing, -} from './dashboard_listing'; +import { DashboardListing } from './dashboard_listing'; -const find = (num) => { +const find = num => { const hits = []; for (let i = 0; i < num; i++) { hits.push({ id: `dashboard${i}`, title: `dashboard${i} title`, - description: `dashboard${i} desc` + description: `dashboard${i} desc`, }); } return Promise.resolve({ total: num, - hits: hits + hits: hits, }); }; test('renders empty page in before initial fetch to avoid flickering', () => { - const component = shallowWithIntl( {}} - createItem={() => {}} - editItem={() => {}} - getViewUrl={() => {}} - listingLimit={1000} - hideWriteControls={false} - />); - expect(component).toMatchSnapshot(); -}); - -describe('after fetch', () => { - test('initialFilter', async () => { - const component = shallowWithIntl( {}} createItem={() => {}} @@ -81,8 +72,25 @@ describe('after fetch', () => { getViewUrl={() => {}} listingLimit={1000} hideWriteControls={false} - initialFilter="my dashboard" - />); + /> + ); + expect(component).toMatchSnapshot(); +}); + +describe('after fetch', () => { + test('initialFilter', async () => { + const component = shallow( + {}} + createItem={() => {}} + editItem={() => {}} + getViewUrl={() => {}} + listingLimit={1000} + hideWriteControls={false} + initialFilter="my dashboard" + /> + ); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); @@ -93,15 +101,17 @@ describe('after fetch', () => { }); test('renders table rows', async () => { - const component = shallowWithIntl( {}} - createItem={() => {}} - editItem={() => {}} - getViewUrl={() => {}} - listingLimit={1000} - hideWriteControls={false} - />); + const component = shallow( + {}} + createItem={() => {}} + editItem={() => {}} + getViewUrl={() => {}} + listingLimit={1000} + hideWriteControls={false} + /> + ); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); @@ -112,15 +122,17 @@ describe('after fetch', () => { }); test('renders call to action when no dashboards exist', async () => { - const component = shallowWithIntl( {}} - createItem={() => {}} - editItem={() => {}} - getViewUrl={() => {}} - listingLimit={1} - hideWriteControls={false} - />); + const component = shallow( + {}} + createItem={() => {}} + editItem={() => {}} + getViewUrl={() => {}} + listingLimit={1} + hideWriteControls={false} + /> + ); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); @@ -131,15 +143,17 @@ describe('after fetch', () => { }); test('hideWriteControls', async () => { - const component = shallowWithIntl( {}} - createItem={() => {}} - editItem={() => {}} - getViewUrl={() => {}} - listingLimit={1} - hideWriteControls={true} - />); + const component = shallow( + {}} + createItem={() => {}} + editItem={() => {}} + getViewUrl={() => {}} + listingLimit={1} + hideWriteControls={true} + /> + ); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); @@ -150,15 +164,17 @@ describe('after fetch', () => { }); test('renders warning when listingLimit is exceeded', async () => { - const component = shallowWithIntl( {}} - createItem={() => {}} - editItem={() => {}} - getViewUrl={() => {}} - listingLimit={1} - hideWriteControls={false} - />); + const component = shallow( + {}} + createItem={() => {}} + editItem={() => {}} + getViewUrl={() => {}} + listingLimit={1} + hideWriteControls={false} + /> + ); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); diff --git a/src/legacy/core_plugins/kibana/public/dashboard/top_nav/clone_modal.test.js b/src/legacy/core_plugins/kibana/public/dashboard/top_nav/clone_modal.test.js index b6e2856cfee74..ac3bf7ed2d794 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/top_nav/clone_modal.test.js +++ b/src/legacy/core_plugins/kibana/public/dashboard/top_nav/clone_modal.test.js @@ -19,55 +19,48 @@ import React from 'react'; import sinon from 'sinon'; -import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers'; -import { - findTestSubject, -} from '@elastic/eui/lib/test'; +import { shallowWithI18nProvider, mountWithI18nProvider } from 'test_utils/enzyme_helpers'; +import { findTestSubject } from '@elastic/eui/lib/test'; -import { - DashboardCloneModal, -} from './clone_modal'; +import { DashboardCloneModal } from './clone_modal'; let onClone; let onClose; -let component; beforeEach(() => { onClone = sinon.spy(); onClose = sinon.spy(); }); -function createComponent(creationMethod = mountWithIntl) { - component = creationMethod( - - ); -} - test('renders DashboardCloneModal', () => { - createComponent(shallowWithIntl); + const component = shallowWithI18nProvider( + + ); expect(component).toMatchSnapshot(); // eslint-disable-line }); test('onClone', () => { - createComponent(); + const component = mountWithI18nProvider( + + ); findTestSubject(component, 'cloneConfirmButton').simulate('click'); sinon.assert.calledWith(onClone, 'dash title'); sinon.assert.notCalled(onClose); }); test('onClose', () => { - createComponent(); + const component = mountWithI18nProvider( + + ); findTestSubject(component, 'cloneCancelButton').simulate('click'); sinon.assert.calledOnce(onClose); sinon.assert.notCalled(onClone); }); test('title', () => { - createComponent(); + const component = mountWithI18nProvider( + + ); const event = { target: { value: 'a' } }; component.find('input').simulate('change', event); findTestSubject(component, 'cloneConfirmButton').simulate('click'); diff --git a/src/legacy/core_plugins/kibana/public/dashboard/top_nav/clone_modal.tsx b/src/legacy/core_plugins/kibana/public/dashboard/top_nav/clone_modal.tsx index f216dcf4506e4..e5e75e4b7d277 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/top_nav/clone_modal.tsx +++ b/src/legacy/core_plugins/kibana/public/dashboard/top_nav/clone_modal.tsx @@ -18,7 +18,8 @@ */ import React, { Fragment } from 'react'; -import { injectI18n, FormattedMessage, InjectedIntl } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import { EuiButton, @@ -43,7 +44,6 @@ interface Props { ) => Promise; onClose: () => void; title: string; - intl: InjectedIntl; } interface State { @@ -53,7 +53,7 @@ interface State { isLoading: boolean; } -class DashboardCloneModalUi extends React.Component { +export class DashboardCloneModal extends React.Component { private isMounted = false; constructor(props: Props) { @@ -117,15 +117,12 @@ class DashboardCloneModalUi extends React.Component { @@ -215,5 +212,3 @@ class DashboardCloneModalUi extends React.Component { ); } } - -export const DashboardCloneModal = injectI18n(DashboardCloneModalUi); diff --git a/src/legacy/core_plugins/kibana/public/dashboard/top_nav/options.tsx b/src/legacy/core_plugins/kibana/public/dashboard/top_nav/options.tsx index 07c8c392bd805..af284e6f557cb 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/top_nav/options.tsx +++ b/src/legacy/core_plugins/kibana/public/dashboard/top_nav/options.tsx @@ -18,7 +18,7 @@ */ import React, { Component } from 'react'; -import { injectI18n, InjectedIntl } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; import { EuiForm, EuiFormRow, EuiSwitch } from '@elastic/eui'; @@ -27,7 +27,6 @@ interface Props { onUseMarginsChange: (useMargins: boolean) => void; hidePanelTitles: boolean; onHidePanelTitlesChange: (hideTitles: boolean) => void; - intl: InjectedIntl; } interface State { @@ -35,7 +34,7 @@ interface State { hidePanelTitles: boolean; } -class OptionsMenuUi extends Component { +export class OptionsMenu extends Component { state = { useMargins: this.props.useMargins, hidePanelTitles: this.props.hidePanelTitles, @@ -62,10 +61,12 @@ class OptionsMenuUi extends Component { { { ); } } - -export const OptionsMenu = injectI18n(OptionsMenuUi); diff --git a/src/legacy/core_plugins/kibana/public/dashboard/top_nav/save_modal.test.js b/src/legacy/core_plugins/kibana/public/dashboard/top_nav/save_modal.test.js index ceee75055fa90..153a049276cee 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/top_nav/save_modal.test.js +++ b/src/legacy/core_plugins/kibana/public/dashboard/top_nav/save_modal.test.js @@ -18,20 +18,20 @@ */ import React from 'react'; -import { shallowWithIntl } from 'test_utils/enzyme_helpers'; +import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers'; -import { - DashboardSaveModal, -} from './save_modal'; +import { DashboardSaveModal } from './save_modal'; test('renders DashboardSaveModal', () => { - const component = shallowWithIntl( {}} - onClose={() => {}} - title="dash title" - description="dash description" - timeRestore={true} - showCopyOnSave={true} - />); + const component = shallowWithI18nProvider( + {}} + onClose={() => {}} + title="dash title" + description="dash description" + timeRestore={true} + showCopyOnSave={true} + /> + ); expect(component).toMatchSnapshot(); // eslint-disable-line }); diff --git a/src/legacy/core_plugins/kibana/public/dashboard/top_nav/save_modal.tsx b/src/legacy/core_plugins/kibana/public/dashboard/top_nav/save_modal.tsx index d889d4be16fc6..47455f04ba809 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/top_nav/save_modal.tsx +++ b/src/legacy/core_plugins/kibana/public/dashboard/top_nav/save_modal.tsx @@ -18,7 +18,7 @@ */ import React, { Fragment } from 'react'; -import { injectI18n, FormattedMessage, InjectedIntl } from '@kbn/i18n/react'; +import { FormattedMessage } from '@kbn/i18n/react'; import { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_save_modal'; import { EuiFormRow, EuiTextArea, EuiSwitch } from '@elastic/eui'; @@ -46,7 +46,6 @@ interface Props { description: string; timeRestore: boolean; showCopyOnSave: boolean; - intl: InjectedIntl; } interface State { @@ -54,7 +53,7 @@ interface State { timeRestore: boolean; } -class DashboardSaveModalUi extends React.Component { +export class DashboardSaveModal extends React.Component { state: State = { description: this.props.description, timeRestore: this.props.timeRestore, @@ -152,5 +151,3 @@ class DashboardSaveModalUi extends React.Component { ); } } - -export const DashboardSaveModal = injectI18n(DashboardSaveModalUi); diff --git a/src/test_utils/public/enzyme_helpers.tsx b/src/test_utils/public/enzyme_helpers.tsx index 17027bd8dce48..43ec49c5c1404 100644 --- a/src/test_utils/public/enzyme_helpers.tsx +++ b/src/test_utils/public/enzyme_helpers.tsx @@ -128,3 +128,15 @@ export function renderWithIntl( } export const nextTick = () => new Promise(res => process.nextTick(res)); + +export function shallowWithI18nProvider(child: ReactElement) { + const wrapped = shallow({child}); + const name = typeof child.type === 'string' ? child.type : child.type.name; + return wrapped.find(name).dive(); +} + +export function mountWithI18nProvider(child: ReactElement) { + const wrapped = mount({child}); + const name = typeof child.type === 'string' ? child.type : child.type.name; + return wrapped.find(name); +}