Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions superset-frontend/src/explore/components/SaveModal.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
Expand Down Expand Up @@ -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();
});
2 changes: 2 additions & 0 deletions superset-frontend/src/explore/components/SaveModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
Expand Down
Loading