diff --git a/superset-frontend/src/explore/actions/hydrateExplore.test.ts b/superset-frontend/src/explore/actions/hydrateExplore.test.ts index 31afeb01c9d8..b31950f784ec 100644 --- a/superset-frontend/src/explore/actions/hydrateExplore.test.ts +++ b/superset-frontend/src/explore/actions/hydrateExplore.test.ts @@ -21,6 +21,10 @@ import { VizType } from '@superset-ui/core'; import { hydrateExplore, HYDRATE_EXPLORE } from './hydrateExplore'; import { exploreInitialData } from '../fixtures'; +afterEach(() => { + window.history.pushState({}, '', '/'); +}); + test('creates hydrate action from initial data', () => { const dispatch = jest.fn(); const getState = jest.fn(() => ({ @@ -168,6 +172,84 @@ test('creates hydrate action with existing state', () => { ); }); +test('hydrates sliceName from preview form data before saved slice name', () => { + window.history.pushState({}, '', '/explore/?form_data_key=preview-key'); + + const dispatch = jest.fn(); + const getState = jest.fn(() => ({ + user: {}, + charts: {}, + datasources: {}, + common: {}, + explore: {}, + })); + const previewSliceName = 'RENAMED - Bug Evidence'; + const savedSliceName = 'Most Populated Countries'; + const previewInitialData = { + ...exploreInitialData, + form_data: { + ...exploreInitialData.form_data, + slice_name: previewSliceName, + }, + slice: { + ...exploreInitialData.slice!, + slice_name: savedSliceName, + }, + }; + + // @ts-expect-error we only need the fields consumed by hydrateExplore + hydrateExplore(previewInitialData)(dispatch, getState); + + expect(dispatch).toHaveBeenCalledWith( + expect.objectContaining({ + type: HYDRATE_EXPLORE, + data: expect.objectContaining({ + explore: expect.objectContaining({ + sliceName: previewSliceName, + }), + }), + }), + ); +}); + +test('hydrates sliceName from saved slice when regular form data has stale name', () => { + const dispatch = jest.fn(); + const getState = jest.fn(() => ({ + user: {}, + charts: {}, + datasources: {}, + common: {}, + explore: {}, + })); + const staleFormDataSliceName = 'Stale Params Name'; + const savedSliceName = 'Current Saved Name'; + const savedChartInitialData = { + ...exploreInitialData, + form_data: { + ...exploreInitialData.form_data, + slice_name: staleFormDataSliceName, + }, + slice: { + ...exploreInitialData.slice!, + slice_name: savedSliceName, + }, + }; + + // @ts-expect-error we only need the fields consumed by hydrateExplore + hydrateExplore(savedChartInitialData)(dispatch, getState); + + expect(dispatch).toHaveBeenCalledWith( + expect.objectContaining({ + type: HYDRATE_EXPLORE, + data: expect.objectContaining({ + explore: expect.objectContaining({ + sliceName: savedSliceName, + }), + }), + }), + ); +}); + test('uses configured default time range if not set', () => { const dispatch = jest.fn(); const getState = jest.fn(() => ({ diff --git a/superset-frontend/src/explore/actions/hydrateExplore.ts b/superset-frontend/src/explore/actions/hydrateExplore.ts index 574707975c25..fcfdb4968727 100644 --- a/superset-frontend/src/explore/actions/hydrateExplore.ts +++ b/superset-frontend/src/explore/actions/hydrateExplore.ts @@ -77,6 +77,12 @@ export const hydrateExplore = const fallbackSlice = sliceId ? sliceEntities?.slices?.[sliceId] : null; const initialSlice = slice ?? fallbackSlice; const initialFormData = form_data ?? initialSlice?.form_data; + const isCachedFormData = getUrlParam(URL_PARAMS.formDataKey) !== null; + const [primarySliceNameSource, fallbackSliceNameSource] = isCachedFormData + ? [initialFormData, initialSlice] + : [initialSlice, initialFormData]; + const initialSliceName = + primarySliceNameSource?.slice_name ?? fallbackSliceNameSource?.slice_name; if (!initialFormData.viz_type) { const defaultVizType = common?.conf.DEFAULT_VIZ_TYPE || VizType.Table; initialFormData.viz_type = @@ -183,6 +189,7 @@ export const hydrateExplore = // because `bootstrapData.controls` is undefined. controls: initialControls, form_data: initialFormData, + sliceName: initialSliceName, slice: initialSlice, controlsTransferred: explore.controlsTransferred, standalone: getUrlParam(URL_PARAMS.standalone), diff --git a/superset-frontend/src/explore/components/SaveModal.test.tsx b/superset-frontend/src/explore/components/SaveModal.test.tsx index 1c79be556f5f..e4fdf217ceb5 100644 --- a/superset-frontend/src/explore/components/SaveModal.test.tsx +++ b/superset-frontend/src/explore/components/SaveModal.test.tsx @@ -179,6 +179,33 @@ test('renders the right footer buttons', () => { ).toBeInTheDocument(); }); +test('initializes chart name from current Explore slice name', () => { + const previewSliceName = 'RENAMED - Bug Evidence'; + const savedSliceName = 'Most Populated Countries'; + const { getByTestId } = setup( + { + ...defaultProps, + form_data: { + ...defaultProps.form_data, + slice_name: previewSliceName, + }, + sliceName: previewSliceName, + }, + mockStore({ + ...initialState, + explore: { + ...initialState.explore, + slice: { + ...initialState.explore.slice, + slice_name: savedSliceName, + }, + }, + }), + ); + + expect(getByTestId('new-chart-name')).toHaveValue(previewSliceName); +}); + test('does not render a message when overriding', () => { const { getByRole, queryByRole } = setup();