From e36a7b6ff1aee3cbbc46bfe1c40095042ab992c3 Mon Sep 17 00:00:00 2001 From: "opensearch-workspace-development[bot]" <144193788+opensearch-workspace-development[bot]@users.noreply.github.com> Date: Thu, 12 Oct 2023 15:33:01 +0800 Subject: [PATCH] [Backport workspace] patch with retire dashboard management and add unit test for mountWrapper (#224) * feat: add unit test for mountWrapper (#223) Signed-off-by: SuZhou-Joe (cherry picked from commit 0906bf473762c19809e065779b1ef474a0ebe8c8) Signed-off-by: github-actions[bot] * feat: add patch Signed-off-by: SuZhou-Joe * feat: some update Signed-off-by: SuZhou-Joe * feat: update snapshot Signed-off-by: SuZhou-Joe --------- Signed-off-by: SuZhou-Joe Signed-off-by: github-actions[bot] Co-authored-by: github-actions[bot] Co-authored-by: tygao Co-authored-by: SuZhou-Joe --- .../__snapshots__/page_wrapper.test.tsx.snap | 13 +++ .../page_wrapper/page_wrapper.test.tsx | 16 ++++ .../components/page_wrapper/page_wrapper.tsx | 4 +- .../mount_management_section.tsx | 22 ++--- .../__snapshots__/page_wrapper.test.tsx.snap | 13 +++ .../page_wrapper/page_wrapper.test.tsx | 16 ++++ .../components/page_wrapper/page_wrapper.tsx | 4 +- .../components/new_theme_modal.tsx | 4 +- .../opensearch_dashboards.json | 2 +- .../mount_management_section.tsx | 80 +++++++++++-------- .../index_pattern_management/public/plugin.ts | 11 +-- .../management_section/mount_section.tsx | 61 +++++++------- .../objects_table/saved_objects_table.tsx | 1 - .../__snapshots__/page_wrapper.test.tsx.snap | 13 +++ .../management_section/page_wrapper/index.ts | 6 ++ .../page_wrapper/page_wrapper.test.tsx | 16 ++++ .../page_wrapper/page_wrapper.tsx | 21 +++++ .../saved_objects_table_page.tsx | 6 -- .../public/plugin.test.ts | 63 +++++++++++++-- .../saved_objects_management/public/plugin.ts | 7 +- 20 files changed, 262 insertions(+), 117 deletions(-) create mode 100644 src/plugins/advanced_settings/public/management_app/components/page_wrapper/__snapshots__/page_wrapper.test.tsx.snap create mode 100644 src/plugins/advanced_settings/public/management_app/components/page_wrapper/page_wrapper.test.tsx create mode 100644 src/plugins/data_source_management/public/components/page_wrapper/__snapshots__/page_wrapper.test.tsx.snap create mode 100644 src/plugins/data_source_management/public/components/page_wrapper/page_wrapper.test.tsx create mode 100644 src/plugins/saved_objects_management/public/management_section/page_wrapper/__snapshots__/page_wrapper.test.tsx.snap create mode 100644 src/plugins/saved_objects_management/public/management_section/page_wrapper/index.ts create mode 100644 src/plugins/saved_objects_management/public/management_section/page_wrapper/page_wrapper.test.tsx create mode 100644 src/plugins/saved_objects_management/public/management_section/page_wrapper/page_wrapper.tsx diff --git a/src/plugins/advanced_settings/public/management_app/components/page_wrapper/__snapshots__/page_wrapper.test.tsx.snap b/src/plugins/advanced_settings/public/management_app/components/page_wrapper/__snapshots__/page_wrapper.test.tsx.snap new file mode 100644 index 000000000000..3c5257e2e8d1 --- /dev/null +++ b/src/plugins/advanced_settings/public/management_app/components/page_wrapper/__snapshots__/page_wrapper.test.tsx.snap @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`PageWrapper should render normally 1`] = ` +
+
+ Foo +
+
+`; diff --git a/src/plugins/advanced_settings/public/management_app/components/page_wrapper/page_wrapper.test.tsx b/src/plugins/advanced_settings/public/management_app/components/page_wrapper/page_wrapper.test.tsx new file mode 100644 index 000000000000..550eb3ee1cae --- /dev/null +++ b/src/plugins/advanced_settings/public/management_app/components/page_wrapper/page_wrapper.test.tsx @@ -0,0 +1,16 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React from 'react'; +import { render } from '@testing-library/react'; +import { PageWrapper } from './page_wrapper'; + +describe('PageWrapper', () => { + it('should render normally', async () => { + const { findByText, container } = render(Foo); + await findByText('Foo'); + expect(container).toMatchSnapshot(); + }); +}); diff --git a/src/plugins/advanced_settings/public/management_app/components/page_wrapper/page_wrapper.tsx b/src/plugins/advanced_settings/public/management_app/components/page_wrapper/page_wrapper.tsx index e0b725edc42d..1b1949c334e4 100644 --- a/src/plugins/advanced_settings/public/management_app/components/page_wrapper/page_wrapper.tsx +++ b/src/plugins/advanced_settings/public/management_app/components/page_wrapper/page_wrapper.tsx @@ -6,10 +6,10 @@ import { EuiPageContent } from '@elastic/eui'; import React from 'react'; -export const PageWrapper = (props: { fullWidth?: boolean; children?: React.ReactChild }) => { +export const PageWrapper = (props: { children?: React.ReactChild }) => { return ( { - const wrapBreadcrumb = (item: ChromeBreadcrumb, scopedHistory: ScopedHistory) => ({ + chrome.setBreadcrumbs([ + ...crumb.map((item) => ({ ...item, - ...(item.href ? reactRouterNavigate(scopedHistory, item.href) : {}), - }); - - chrome.setBreadcrumbs([...crumbs.map((item) => wrapBreadcrumb(item, params.history))]); - }; - setBreadcrumbsScoped(crumb); + ...(item.href ? reactRouterNavigate(params.history, item.href) : {}), + })), + ]); const canSave = application.capabilities.advancedSettings.save as boolean; diff --git a/src/plugins/data_source_management/public/components/page_wrapper/__snapshots__/page_wrapper.test.tsx.snap b/src/plugins/data_source_management/public/components/page_wrapper/__snapshots__/page_wrapper.test.tsx.snap new file mode 100644 index 000000000000..3c5257e2e8d1 --- /dev/null +++ b/src/plugins/data_source_management/public/components/page_wrapper/__snapshots__/page_wrapper.test.tsx.snap @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`PageWrapper should render normally 1`] = ` +
+
+ Foo +
+
+`; diff --git a/src/plugins/data_source_management/public/components/page_wrapper/page_wrapper.test.tsx b/src/plugins/data_source_management/public/components/page_wrapper/page_wrapper.test.tsx new file mode 100644 index 000000000000..550eb3ee1cae --- /dev/null +++ b/src/plugins/data_source_management/public/components/page_wrapper/page_wrapper.test.tsx @@ -0,0 +1,16 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React from 'react'; +import { render } from '@testing-library/react'; +import { PageWrapper } from './page_wrapper'; + +describe('PageWrapper', () => { + it('should render normally', async () => { + const { findByText, container } = render(Foo); + await findByText('Foo'); + expect(container).toMatchSnapshot(); + }); +}); diff --git a/src/plugins/data_source_management/public/components/page_wrapper/page_wrapper.tsx b/src/plugins/data_source_management/public/components/page_wrapper/page_wrapper.tsx index e0b725edc42d..1b1949c334e4 100644 --- a/src/plugins/data_source_management/public/components/page_wrapper/page_wrapper.tsx +++ b/src/plugins/data_source_management/public/components/page_wrapper/page_wrapper.tsx @@ -6,10 +6,10 @@ import { EuiPageContent } from '@elastic/eui'; import React from 'react'; -export const PageWrapper = (props: { fullWidth?: boolean; children?: React.ReactChild }) => { +export const PageWrapper = (props: { children?: React.ReactChild }) => { return ( = ({ addBasePath, onClose }) => { modes. You or your administrator can change to the previous theme by visiting {advancedSettingsLink}." values={{ advancedSettingsLink: ( - + , - params: ManagementAppMountParams, + params: AppMountParameters, getMlCardState: () => MlCardState ) { const [ @@ -75,6 +82,17 @@ export async function mountManagementSection( chrome.setBadge(readOnlyBadge); } + const setBreadcrumbsScope = (crumbs: ChromeBreadcrumb[] = [], appHistory?: ScopedHistory) => { + const wrapBreadcrumb = (item: ChromeBreadcrumb, scopedHistory: ScopedHistory) => ({ + ...item, + ...(item.href ? reactRouterNavigate(scopedHistory, item.href) : {}), + }); + + chrome.setBreadcrumbs([ + ...crumbs.map((item) => wrapBreadcrumb(item, appHistory || params.history)), + ]); + }; + const deps: IndexPatternManagmentContext = { chrome, application, @@ -86,40 +104,36 @@ export async function mountManagementSection( docLinks, data, indexPatternManagementStart: indexPatternManagementStart as IndexPatternManagementStart, - setBreadcrumbs: params.setBreadcrumbs, + setBreadcrumbs: setBreadcrumbsScope, getMlCardState, dataSourceEnabled, }; - const router = ( - - - - - - - - - - - - - - - - - ); - - const content = ( - - {router} - - ); - ReactDOM.render( - - {content} - , + + + + + + + + + + + + + + + + + + + + + + + + , params.element ); diff --git a/src/plugins/index_pattern_management/public/plugin.ts b/src/plugins/index_pattern_management/public/plugin.ts index cdac2c9d982d..758c81ee538f 100644 --- a/src/plugins/index_pattern_management/public/plugin.ts +++ b/src/plugins/index_pattern_management/public/plugin.ts @@ -47,12 +47,11 @@ import { IndexPatternManagementServiceStart, } from './service'; -import { ManagementAppMountParams, ManagementSetup } from '../../management/public'; +import { ManagementAppMountParams } from '../../management/public'; import { DEFAULT_APP_CATEGORIES } from '../../../core/public'; import { reactRouterNavigate } from '../../opensearch_dashboards_react/public'; export interface IndexPatternManagementSetupDependencies { - management: ManagementSetup; urlForwarding: UrlForwardingSetup; } @@ -85,14 +84,8 @@ export class IndexPatternManagementPlugin public setup( core: CoreSetup, - { management, urlForwarding }: IndexPatternManagementSetupDependencies + { urlForwarding }: IndexPatternManagementSetupDependencies ) { - const opensearchDashboardsSection = management.sections.section.opensearchDashboards; - - if (!opensearchDashboardsSection) { - throw new Error('`opensearchDashboards` management section not found.'); - } - const newAppPath = IPM_APP_ID; const legacyPatternsPath = 'management/opensearch-dashboards/index_patterns'; diff --git a/src/plugins/saved_objects_management/public/management_section/mount_section.tsx b/src/plugins/saved_objects_management/public/management_section/mount_section.tsx index c19f8ccdd96a..6a92e71da702 100644 --- a/src/plugins/saved_objects_management/public/management_section/mount_section.tsx +++ b/src/plugins/saved_objects_management/public/management_section/mount_section.tsx @@ -35,45 +35,35 @@ import { I18nProvider } from '@osd/i18n/react'; import { EuiLoadingSpinner } from '@elastic/eui'; import { AppMountParameters, CoreSetup } from 'src/core/public'; import { ManagementAppMountParams } from 'src/plugins/management/public'; +import { PageWrapper } from './page_wrapper'; import { StartDependencies, SavedObjectsManagementPluginStart } from '../plugin'; import { ISavedObjectsManagementServiceRegistry } from '../services'; import { getAllowedTypes } from './../lib'; -import { WORKSPACE_TYPE } from '../../../../core/public'; interface MountParams { core: CoreSetup; serviceRegistry: ISavedObjectsManagementServiceRegistry; - mountParams?: ManagementAppMountParams; appMountParams?: AppMountParameters; title: string; allowedObjectTypes?: string[]; - fullWidth?: boolean; } const SavedObjectsEditionPage = lazy(() => import('./saved_objects_edition_page')); const SavedObjectsTablePage = lazy(() => import('./saved_objects_table_page')); export const mountManagementSection = async ({ core, - mountParams, appMountParams, serviceRegistry, title, allowedObjectTypes, - fullWidth = true, }: MountParams) => { const [coreStart, { data, uiActions }, pluginStart] = await core.getStartServices(); - const usedMountParams = mountParams || appMountParams || ({} as ManagementAppMountParams); + const usedMountParams = appMountParams || ({} as ManagementAppMountParams); const { element, history } = usedMountParams; const { chrome } = coreStart; - const setBreadcrumbs = mountParams?.setBreadcrumbs || chrome.setBreadcrumbs; - let finalAllowedObjectTypes = allowedObjectTypes; - if (finalAllowedObjectTypes === undefined) { - /** - * Workspace needs to be filtered out since it is a concept with higher level than normal saved objects. - */ - finalAllowedObjectTypes = (await getAllowedTypes(coreStart.http)).filter( - (item) => item !== WORKSPACE_TYPE - ); + const setBreadcrumbs = chrome.setBreadcrumbs; + if (allowedObjectTypes === undefined) { + allowedObjectTypes = await getAllowedTypes(coreStart.http); } coreStart.chrome.docTitle.change(title); @@ -97,31 +87,34 @@ export const mountManagementSection = async ({ }> - + + + }> - + + + diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index fc1592c68cae..2c3ed50df9db 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -121,7 +121,6 @@ export interface SavedObjectsTableProps { canGoInApp: (obj: SavedObjectWithMetadata) => boolean; dateFormat: string; title: string; - fullWidth: boolean; } export interface SavedObjectsTableState { diff --git a/src/plugins/saved_objects_management/public/management_section/page_wrapper/__snapshots__/page_wrapper.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/page_wrapper/__snapshots__/page_wrapper.test.tsx.snap new file mode 100644 index 000000000000..3c5257e2e8d1 --- /dev/null +++ b/src/plugins/saved_objects_management/public/management_section/page_wrapper/__snapshots__/page_wrapper.test.tsx.snap @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`PageWrapper should render normally 1`] = ` +
+
+ Foo +
+
+`; diff --git a/src/plugins/saved_objects_management/public/management_section/page_wrapper/index.ts b/src/plugins/saved_objects_management/public/management_section/page_wrapper/index.ts new file mode 100644 index 000000000000..3cf0cdd26c99 --- /dev/null +++ b/src/plugins/saved_objects_management/public/management_section/page_wrapper/index.ts @@ -0,0 +1,6 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export { PageWrapper } from './page_wrapper'; diff --git a/src/plugins/saved_objects_management/public/management_section/page_wrapper/page_wrapper.test.tsx b/src/plugins/saved_objects_management/public/management_section/page_wrapper/page_wrapper.test.tsx new file mode 100644 index 000000000000..550eb3ee1cae --- /dev/null +++ b/src/plugins/saved_objects_management/public/management_section/page_wrapper/page_wrapper.test.tsx @@ -0,0 +1,16 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React from 'react'; +import { render } from '@testing-library/react'; +import { PageWrapper } from './page_wrapper'; + +describe('PageWrapper', () => { + it('should render normally', async () => { + const { findByText, container } = render(Foo); + await findByText('Foo'); + expect(container).toMatchSnapshot(); + }); +}); diff --git a/src/plugins/saved_objects_management/public/management_section/page_wrapper/page_wrapper.tsx b/src/plugins/saved_objects_management/public/management_section/page_wrapper/page_wrapper.tsx new file mode 100644 index 000000000000..1b1949c334e4 --- /dev/null +++ b/src/plugins/saved_objects_management/public/management_section/page_wrapper/page_wrapper.tsx @@ -0,0 +1,21 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { EuiPageContent } from '@elastic/eui'; +import React from 'react'; + +export const PageWrapper = (props: { children?: React.ReactChild }) => { + return ( + + ); +}; diff --git a/src/plugins/saved_objects_management/public/management_section/saved_objects_table_page.tsx b/src/plugins/saved_objects_management/public/management_section/saved_objects_table_page.tsx index d37ba4c7ee95..3e8121c7c2f5 100644 --- a/src/plugins/saved_objects_management/public/management_section/saved_objects_table_page.tsx +++ b/src/plugins/saved_objects_management/public/management_section/saved_objects_table_page.tsx @@ -50,7 +50,6 @@ const SavedObjectsTablePage = ({ namespaceRegistry, setBreadcrumbs, title, - fullWidth, }: { coreStart: CoreStart; dataStart: DataPublicPluginStart; @@ -61,7 +60,6 @@ const SavedObjectsTablePage = ({ namespaceRegistry: SavedObjectsManagementNamespaceServiceStart; setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => void; title: string; - fullWidth: boolean; }) => { const capabilities = coreStart.application.capabilities; const itemsPerPage = coreStart.uiSettings.get('savedObjects:perPage', 50); @@ -71,9 +69,6 @@ const SavedObjectsTablePage = ({ setBreadcrumbs([ { text: title, - /** - * There is no need to set a link for current bread crumb - */ href: undefined, }, ]); @@ -109,7 +104,6 @@ const SavedObjectsTablePage = ({ return inAppUrl ? Boolean(get(capabilities, inAppUrl.uiCapabilitiesPath)) : false; }} title={title} - fullWidth={fullWidth} /> ); }; diff --git a/src/plugins/saved_objects_management/public/plugin.test.ts b/src/plugins/saved_objects_management/public/plugin.test.ts index c8e762f73dcc..149cee7c5c86 100644 --- a/src/plugins/saved_objects_management/public/plugin.test.ts +++ b/src/plugins/saved_objects_management/public/plugin.test.ts @@ -28,12 +28,23 @@ * under the License. */ +const mountManagementSectionMock = jest.fn(); +jest.doMock('./management_section', () => ({ + mountManagementSection: mountManagementSectionMock, +})); +import { waitFor } from '@testing-library/dom'; import { coreMock } from '../../../core/public/mocks'; import { homePluginMock } from '../../home/public/mocks'; import { managementPluginMock } from '../../management/public/mocks'; import { dataPluginMock } from '../../data/public/mocks'; import { uiActionsPluginMock } from '../../ui_actions/public/mocks'; import { SavedObjectsManagementPlugin } from './plugin'; +import { + MANAGE_LIBRARY_TITLE_WORDINGS, + SAVED_QUERIES_WORDINGS, + SAVED_SEARCHES_WORDINGS, +} from './constants'; +import { DEFAULT_APP_CATEGORIES } from '../../../core/public'; describe('SavedObjectsManagementPlugin', () => { let plugin: SavedObjectsManagementPlugin; @@ -50,12 +61,22 @@ describe('SavedObjectsManagementPlugin', () => { const homeSetup = homePluginMock.createSetupContract(); const managementSetup = managementPluginMock.createSetupContract(); const uiActionsSetup = uiActionsPluginMock.createSetupContract(); + const registerMock = jest.fn((params) => params.mount({} as any, {} as any)); - await plugin.setup(coreSetup, { - home: homeSetup, - management: managementSetup, - uiActions: uiActionsSetup, - }); + await plugin.setup( + { + ...coreSetup, + application: { + ...coreSetup.application, + register: registerMock, + }, + }, + { + home: homeSetup, + management: managementSetup, + uiActions: uiActionsSetup, + } + ); expect(homeSetup.featureCatalogue.register).toHaveBeenCalledTimes(1); expect(homeSetup.featureCatalogue.register).toHaveBeenCalledWith( @@ -63,6 +84,38 @@ describe('SavedObjectsManagementPlugin', () => { id: 'saved_objects', }) ); + expect(registerMock).toBeCalledWith( + expect.objectContaining({ + id: 'objects', + title: MANAGE_LIBRARY_TITLE_WORDINGS, + order: 10000, + category: DEFAULT_APP_CATEGORIES.opensearchDashboards, + }) + ); + expect(registerMock).toBeCalledWith( + expect.objectContaining({ + id: 'objects_searches', + title: SAVED_SEARCHES_WORDINGS, + order: 8000, + category: DEFAULT_APP_CATEGORIES.opensearchDashboards, + }) + ); + expect(registerMock).toBeCalledWith( + expect.objectContaining({ + id: 'objects_query', + title: SAVED_QUERIES_WORDINGS, + order: 8001, + category: DEFAULT_APP_CATEGORIES.opensearchDashboards, + }) + ); + waitFor( + () => { + expect(mountManagementSectionMock).toBeCalledTimes(3); + }, + { + container: document.body, + } + ); }); }); }); diff --git a/src/plugins/saved_objects_management/public/plugin.ts b/src/plugins/saved_objects_management/public/plugin.ts index a7e1c0d1a1cb..dba28e05e98e 100644 --- a/src/plugins/saved_objects_management/public/plugin.ts +++ b/src/plugins/saved_objects_management/public/plugin.ts @@ -122,7 +122,6 @@ export class SavedObjectsManagementPlugin appMountParams, title, allowedObjectTypes, - fullWidth: false, }); }; @@ -130,9 +129,7 @@ export class SavedObjectsManagementPlugin * Register saved objects overview & saved search & saved query here */ core.application.register({ - id: 'objects_all', - appRoute: '/app/objects', - exactRoute: true, + id: 'objects', title: MANAGE_LIBRARY_TITLE_WORDINGS, order: 10000, category: DEFAULT_APP_CATEGORIES.opensearchDashboards, @@ -143,7 +140,6 @@ export class SavedObjectsManagementPlugin core.application.register({ id: 'objects_searches', - appRoute: '/app/objects/search', title: SAVED_SEARCHES_WORDINGS, order: 8000, category: DEFAULT_APP_CATEGORIES.opensearchDashboards, @@ -155,7 +151,6 @@ export class SavedObjectsManagementPlugin core.application.register({ id: 'objects_query', - appRoute: '/app/objects/query', title: SAVED_QUERIES_WORDINGS, order: 8001, category: DEFAULT_APP_CATEGORIES.opensearchDashboards,