/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import sinon from 'sinon'; import { SupersetClient } from '@superset-ui/connection'; import { removeSliceFromDashboard, saveDashboardRequest, } from 'src/dashboard/actions/dashboardState'; import { REMOVE_FILTER } from 'src/dashboard/actions/dashboardFilters'; import { UPDATE_COMPONENTS_PARENTS_LIST } from 'src/dashboard/actions/dashboardLayout'; import { DASHBOARD_GRID_ID } from 'src/dashboard/util/constants'; import { filterId, sliceEntitiesForDashboard as sliceEntities, } from '../fixtures/mockSliceEntities'; import { emptyFilters } from '../fixtures/mockDashboardFilters'; import mockDashboardData from '../fixtures/mockDashboardData'; describe('dashboardState actions', () => { const mockState = { dashboardState: { sliceIds: [filterId], hasUnsavedChanges: true, }, dashboardInfo: {}, sliceEntities, dashboardFilters: emptyFilters, dashboardLayout: { past: [], present: mockDashboardData.positions, future: {}, }, }; const newDashboardData = mockDashboardData; let postStub; beforeEach(() => { postStub = sinon .stub(SupersetClient, 'post') .resolves('the value you want to return'); }); afterEach(() => { postStub.restore(); }); function setup(stateOverrides) { const state = { ...mockState, ...stateOverrides }; const getState = sinon.spy(() => state); const dispatch = sinon.stub(); return { getState, dispatch, state }; } describe('saveDashboardRequest', () => { it('should dispatch UPDATE_COMPONENTS_PARENTS_LIST action', () => { const { getState, dispatch } = setup({ dashboardState: { hasUnsavedChanges: false }, }); const thunk = saveDashboardRequest(newDashboardData, 1, 'save_dash'); thunk(dispatch, getState); expect(dispatch.callCount).toBe(1); expect(dispatch.getCall(0).args[0].type).toBe( UPDATE_COMPONENTS_PARENTS_LIST, ); }); it('should post dashboard data with updated redux state', () => { const { getState, dispatch } = setup({ dashboardState: { hasUnsavedChanges: false }, }); // start with mockDashboardData, it didn't have parents attr expect( newDashboardData.positions[DASHBOARD_GRID_ID].parents, ).not.toBeDefined(); // mock redux work: dispatch an event, cause modify redux state const mockParentsList = ['ROOT_ID']; dispatch.callsFake(() => { mockState.dashboardLayout.present[ DASHBOARD_GRID_ID ].parents = mockParentsList; }); // call saveDashboardRequest, it should post dashboard data with updated // layout object (with parents attribute) const thunk = saveDashboardRequest(newDashboardData, 1, 'save_dash'); thunk(dispatch, getState); expect(postStub.callCount).toBe(1); const postPayload = postStub.getCall(0).args[0].postPayload; expect(postPayload.data.positions[DASHBOARD_GRID_ID].parents).toBe( mockParentsList, ); }); }); it('should dispatch removeFilter if a removed slice is a filter_box', () => { const { getState, dispatch } = setup(mockState); const thunk = removeSliceFromDashboard(filterId); thunk(dispatch, getState); const removeFilter = dispatch.getCall(0).args[0]; removeFilter(dispatch, getState); expect(dispatch.getCall(3).args[0].type).toBe(REMOVE_FILTER); }); });