From 12c0075279c1f81a742ac0171fcec6701419392a Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Wed, 3 Nov 2021 16:17:19 +0200 Subject: [PATCH] [Visualize] Fixes wrong header menu when navigating from a dashboard to a by ref viz (#117077) * [Visualize] fixes share inactive button when navigating from a dashboard to a by ref vz * Add unit test * Remove the hardcoded 'dashboards' Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../utils/get_top_nav_config.test.tsx | 211 +++++++++++++++++- .../application/utils/get_top_nav_config.tsx | 13 +- 2 files changed, 215 insertions(+), 9 deletions(-) diff --git a/src/plugins/visualize/public/application/utils/get_top_nav_config.test.tsx b/src/plugins/visualize/public/application/utils/get_top_nav_config.test.tsx index 450654e42585d..19b52d73661a3 100644 --- a/src/plugins/visualize/public/application/utils/get_top_nav_config.test.tsx +++ b/src/plugins/visualize/public/application/utils/get_top_nav_config.test.tsx @@ -5,9 +5,18 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ - +import { Observable } from 'rxjs'; import { Capabilities } from 'src/core/public'; -import { showPublicUrlSwitch } from './get_top_nav_config'; +import { showPublicUrlSwitch, getTopNavConfig, TopNavConfigParams } from './get_top_nav_config'; +import type { + VisualizeEditorVisInstance, + VisualizeAppStateContainer, + VisualizeServices, +} from '../types'; +import { createVisualizeServicesMock } from './mocks'; +import { sharePluginMock } from '../../../../share/public/mocks'; +import { createEmbeddableStateTransferMock } from '../../../../embeddable/public/mocks'; +import { visualizeAppStateStub } from './stubs'; describe('showPublicUrlSwitch', () => { test('returns false if "visualize" app is not available', () => { @@ -49,3 +58,201 @@ describe('showPublicUrlSwitch', () => { expect(result).toBe(true); }); }); + +describe('getTopNavConfig', () => { + const stateContainerGetStateMock = jest.fn(() => visualizeAppStateStub); + const stateContainer = { + getState: stateContainerGetStateMock, + state$: new Observable(), + transitions: { + updateVisState: jest.fn(), + set: jest.fn(), + }, + } as unknown as VisualizeAppStateContainer; + const mockServices = createVisualizeServicesMock(); + const share = sharePluginMock.createStartContract(); + const services = { + ...mockServices, + dashboard: { + dashboardFeatureFlagConfig: { + allowByValueEmbeddables: true, + }, + }, + visualizeCapabilities: { + save: true, + }, + dashboardCapabilities: { + showWriteControls: true, + }, + share, + }; + test('returns correct links for by reference visualization', () => { + const vis = { + savedVis: { + id: 'test', + sharingSavedObjectProps: { + outcome: 'conflict', + aliasTargetId: 'alias_id', + }, + }, + vis: { + type: { + title: 'TSVB', + }, + }, + } as VisualizeEditorVisInstance; + const topNavLinks = getTopNavConfig( + { + hasUnsavedChanges: false, + setHasUnsavedChanges: jest.fn(), + hasUnappliedChanges: false, + onOpenInspector: jest.fn(), + originatingApp: 'dashboards', + setOriginatingApp: jest.fn(), + visInstance: vis, + stateContainer, + visualizationIdFromUrl: undefined, + stateTransfer: createEmbeddableStateTransferMock(), + } as unknown as TopNavConfigParams, + services as unknown as VisualizeServices + ); + + expect(topNavLinks).toMatchInlineSnapshot(` + Array [ + Object { + "description": "Open Inspector for visualization", + "disableButton": [Function], + "id": "inspector", + "label": "inspect", + "run": undefined, + "testId": "openInspectorButton", + "tooltip": [Function], + }, + Object { + "description": "Share Visualization", + "disableButton": false, + "id": "share", + "label": "share", + "run": [Function], + "testId": "shareTopNavButton", + }, + Object { + "description": "Return to the last app without saving changes", + "emphasize": false, + "id": "cancel", + "label": "Cancel", + "run": [Function], + "testId": "visualizeCancelAndReturnButton", + "tooltip": [Function], + }, + Object { + "description": "Save Visualization", + "disableButton": false, + "emphasize": false, + "iconType": undefined, + "id": "save", + "label": "Save as", + "run": [Function], + "testId": "visualizeSaveButton", + "tooltip": [Function], + }, + Object { + "description": "Finish editing visualization and return to the last app", + "disableButton": false, + "emphasize": true, + "iconType": "checkInCircleFilled", + "id": "saveAndReturn", + "label": "Save and return", + "run": [Function], + "testId": "visualizesaveAndReturnButton", + "tooltip": [Function], + }, + ] + `); + }); + + test('returns correct links for by value visualization', () => { + const vis = { + savedVis: { + id: undefined, + sharingSavedObjectProps: { + outcome: 'conflict', + aliasTargetId: 'alias_id', + }, + }, + vis: { + type: { + title: 'TSVB', + }, + }, + } as VisualizeEditorVisInstance; + const topNavLinks = getTopNavConfig( + { + hasUnsavedChanges: false, + setHasUnsavedChanges: jest.fn(), + hasUnappliedChanges: false, + onOpenInspector: jest.fn(), + originatingApp: 'dashboards', + setOriginatingApp: jest.fn(), + visInstance: vis, + stateContainer, + visualizationIdFromUrl: undefined, + stateTransfer: createEmbeddableStateTransferMock(), + } as unknown as TopNavConfigParams, + services as unknown as VisualizeServices + ); + + expect(topNavLinks).toMatchInlineSnapshot(` + Array [ + Object { + "description": "Open Inspector for visualization", + "disableButton": [Function], + "id": "inspector", + "label": "inspect", + "run": undefined, + "testId": "openInspectorButton", + "tooltip": [Function], + }, + Object { + "description": "Share Visualization", + "disableButton": true, + "id": "share", + "label": "share", + "run": [Function], + "testId": "shareTopNavButton", + }, + Object { + "description": "Return to the last app without saving changes", + "emphasize": false, + "id": "cancel", + "label": "Cancel", + "run": [Function], + "testId": "visualizeCancelAndReturnButton", + "tooltip": [Function], + }, + Object { + "description": "Save Visualization", + "disableButton": false, + "emphasize": false, + "iconType": undefined, + "id": "save", + "label": "Save to library", + "run": [Function], + "testId": "visualizeSaveButton", + "tooltip": [Function], + }, + Object { + "description": "Finish editing visualization and return to the last app", + "disableButton": false, + "emphasize": true, + "iconType": "checkInCircleFilled", + "id": "saveAndReturn", + "label": "Save and return", + "run": [Function], + "testId": "visualizesaveAndReturnButton", + "tooltip": [Function], + }, + ] + `); + }); +}); diff --git a/src/plugins/visualize/public/application/utils/get_top_nav_config.tsx b/src/plugins/visualize/public/application/utils/get_top_nav_config.tsx index 9d1c93f25645c..772565734dac4 100644 --- a/src/plugins/visualize/public/application/utils/get_top_nav_config.tsx +++ b/src/plugins/visualize/public/application/utils/get_top_nav_config.tsx @@ -49,7 +49,7 @@ interface VisualizeCapabilities { show: boolean; } -interface TopNavConfigParams { +export interface TopNavConfigParams { hasUnsavedChanges: boolean; setHasUnsavedChanges: (value: boolean) => void; openInspector: () => void; @@ -243,18 +243,17 @@ export const getTopNavConfig = ( const allowByValue = dashboard.dashboardFeatureFlagConfig.allowByValueEmbeddables; const saveButtonLabel = - embeddableId || (!savedVis.id && allowByValue && originatingApp) + !savedVis.id && allowByValue && originatingApp ? i18n.translate('visualize.topNavMenu.saveVisualizationToLibraryButtonLabel', { defaultMessage: 'Save to library', }) - : originatingApp && (embeddableId || savedVis.id) + : originatingApp && savedVis.id ? i18n.translate('visualize.topNavMenu.saveVisualizationAsButtonLabel', { defaultMessage: 'Save as', }) : i18n.translate('visualize.topNavMenu.saveVisualizationButtonLabel', { defaultMessage: 'Save', }); - const showSaveAndReturn = originatingApp && (savedVis?.id || allowByValue); const showSaveButton = @@ -293,7 +292,7 @@ export const getTopNavConfig = ( }), testId: 'shareTopNavButton', run: (anchorElement) => { - if (share && !embeddableId) { + if (share) { const currentState = stateContainer.getState(); const searchParams = parse(history.location.search); const params: VisualizeLocatorParams = { @@ -336,8 +335,8 @@ export const getTopNavConfig = ( }); } }, - // disable the Share button if no action specified - disableButton: !share || !!embeddableId, + // disable the Share button if no action specified and fot byValue visualizations + disableButton: !share || Boolean(!savedVis.id && allowByValue && originatingApp), }, ...(originatingApp ? [