fix(SaveModal): reset chart state when saving and going to a dashboard (#36402)

This commit is contained in:
Mehmet Salih Yavuz
2025-12-03 18:30:08 +03:00
committed by GitHub
parent f955f0d133
commit b40467c7e2
2 changed files with 86 additions and 0 deletions

View File

@@ -30,6 +30,7 @@ import fetchMock from 'fetch-mock';
import * as saveModalActions from 'src/explore/actions/saveModalActions';
import SaveModal, { PureSaveModal } from 'src/explore/components/SaveModal';
import * as dashboardStateActions from 'src/dashboard/actions/dashboardState';
jest.mock('@superset-ui/core/components/Select', () => ({
...jest.requireActual('@superset-ui/core/components/Select/AsyncSelect'),
@@ -345,3 +346,86 @@ test('removes form_data_key from URL parameters after save', () => {
expect(result.get('slice_id')).toEqual('1');
expect(result.get('save_action')).toEqual('overwrite');
});
test('dispatches removeChartState when saving and going to dashboard', async () => {
// Spy on the removeChartState action creator
const removeChartStateSpy = jest.spyOn(
dashboardStateActions,
'removeChartState',
);
// Mock the dashboard API response
const dashboardId = 123;
const dashboardUrl = '/superset/dashboard/test-dashboard/';
fetchMock.get(
`glob:*/api/v1/dashboard/${dashboardId}*`,
{
result: {
id: dashboardId,
dashboard_title: 'Test Dashboard',
url: dashboardUrl,
},
},
{ overwriteRoutes: true },
);
const mockDispatch = jest.fn();
const mockHistory = {
push: jest.fn(),
replace: jest.fn(),
};
const chartId = 42;
const mockUpdateSlice = jest.fn(() => Promise.resolve({ id: chartId }));
const mockSetFormData = jest.fn();
const myProps = {
...defaultProps,
slice: { slice_id: 1, slice_name: 'title', owners: [1] },
actions: {
setFormData: mockSetFormData,
updateSlice: mockUpdateSlice,
getSliceDashboards: jest.fn(() => Promise.resolve([])),
saveSliceFailed: jest.fn(),
},
user: { userId: 1 },
history: mockHistory,
dispatch: mockDispatch,
};
const saveModal = new PureSaveModal(myProps);
saveModal.state = {
action: 'overwrite',
newSliceName: 'test chart',
datasetName: 'test dataset',
dashboard: { label: 'Test Dashboard', value: dashboardId },
saveStatus: null,
};
// Mock onHide to prevent errors
saveModal.onHide = jest.fn();
// Trigger save and go to dashboard (gotodash = true)
await saveModal.saveOrOverwrite(true);
// Wait for async operations
await waitFor(() => {
expect(mockUpdateSlice).toHaveBeenCalled();
expect(mockSetFormData).toHaveBeenCalled();
});
// Verify removeChartState was called with the correct chart ID
expect(removeChartStateSpy).toHaveBeenCalledWith(chartId);
// Verify the action was dispatched (check the action object directly)
expect(mockDispatch).toHaveBeenCalled();
expect(mockDispatch).toHaveBeenCalledWith({
type: 'REMOVE_CHART_STATE',
chartId,
});
// Verify navigation happened
expect(mockHistory.push).toHaveBeenCalled();
// Clean up
removeChartStateSpy.mockRestore();
});

View File

@@ -46,6 +46,7 @@ import { canUserEditDashboard } from 'src/dashboard/util/permissionUtils';
import { setSaveChartModalVisibility } from 'src/explore/actions/saveModalActions';
import { SaveActionType } from 'src/explore/types';
import { UserWithPermissionsAndRoles } from 'src/types/bootstrapTypes';
import { removeChartState } from 'src/dashboard/actions/dashboardState';
import { Dashboard } from 'src/types/Dashboard';
// Session storage key for recent dashboard
@@ -276,6 +277,7 @@ class SaveModal extends Component<SaveModalProps, SaveModalState> {
// Go to new dashboard url
if (gotodash && dashboard) {
this.props.dispatch(removeChartState(value.id));
this.props.history.push(dashboard.url);
return;
}