diff --git a/public/app/features/variables/editor/reducer.test.ts b/public/app/features/variables/editor/reducer.test.ts index 7609e1fd3c6..c43e2345039 100644 --- a/public/app/features/variables/editor/reducer.test.ts +++ b/public/app/features/variables/editor/reducer.test.ts @@ -4,6 +4,7 @@ import { changeVariableEditorExtended, changeVariableNameFailed, changeVariableNameSucceeded, + cleanEditorState, clearIdInEditor, initialVariableEditorState, removeVariableEditorError, @@ -17,7 +18,7 @@ import { toVariablePayload } from '../state/types'; describe('variableEditorReducer', () => { describe('when setIdInEditor is dispatched', () => { - it('then state should be correct ', () => { + it('then state should be correct', () => { const payload = { id: '0' }; reducerTester() .givenReducer(variableEditorReducer, { ...initialVariableEditorState }) @@ -30,7 +31,7 @@ describe('variableEditorReducer', () => { }); describe('when clearIdInEditor is dispatched', () => { - it('then state should be correct ', () => { + it('then state should be correct', () => { reducerTester() .givenReducer(variableEditorReducer, { ...initialVariableEditorState, id: '0' }) .whenActionIsDispatched(clearIdInEditor()) @@ -41,7 +42,7 @@ describe('variableEditorReducer', () => { }); describe('when variableEditorMounted is dispatched', () => { - it('then state should be correct ', () => { + it('then state should be correct', () => { const payload = { name: 'A name' }; reducerTester() .givenReducer(variableEditorReducer, { ...initialVariableEditorState }) @@ -54,7 +55,7 @@ describe('variableEditorReducer', () => { }); describe('when variableEditorUnMounted is dispatched', () => { - it('then state should be correct ', () => { + it('then state should be correct', () => { const initialState = { ...initialVariableEditorState, id: '0', @@ -72,7 +73,7 @@ describe('variableEditorReducer', () => { }); describe('when changeVariableNameSucceeded is dispatched there are other errors', () => { - it('then state should be correct ', () => { + it('then state should be correct', () => { const initialState = { ...initialVariableEditorState, name: 'A duplicate name', @@ -93,7 +94,7 @@ describe('variableEditorReducer', () => { }); describe('when changeVariableNameSucceeded is dispatched there are no other errors', () => { - it('then state should be correct ', () => { + it('then state should be correct', () => { const initialState = { ...initialVariableEditorState, name: 'A duplicate name', @@ -114,7 +115,7 @@ describe('variableEditorReducer', () => { }); describe('when changeVariableNameFailed is dispatched', () => { - it('then state should be correct ', () => { + it('then state should be correct', () => { const payload = { newName: 'Duplicate name', errorText: 'Name is an duplicate' }; reducerTester() .givenReducer(variableEditorReducer, { ...initialVariableEditorState }) @@ -129,7 +130,7 @@ describe('variableEditorReducer', () => { }); describe('when addVariableEditorError is dispatched', () => { - it('then state should be correct ', () => { + it('then state should be correct', () => { const payload = { errorProp: 'someProp', errorText: 'someProp failed' }; reducerTester() .givenReducer(variableEditorReducer, { ...initialVariableEditorState }) @@ -143,7 +144,7 @@ describe('variableEditorReducer', () => { }); describe('when removeVariableEditorError is dispatched and there are other errors', () => { - it('then state should be correct ', () => { + it('then state should be correct', () => { const payload = { errorProp: 'someProp' }; reducerTester() .givenReducer(variableEditorReducer, { @@ -161,7 +162,7 @@ describe('variableEditorReducer', () => { }); describe('when removeVariableEditorError is dispatched and there are no other errors', () => { - it('then state should be correct ', () => { + it('then state should be correct', () => { const payload = { errorProp: 'someProp' }; reducerTester() .givenReducer(variableEditorReducer, { @@ -179,7 +180,7 @@ describe('variableEditorReducer', () => { }); describe('when changeVariableEditorExtended is dispatched', () => { - it('then state should be correct ', () => { + it('then state should be correct', () => { const payload = { propName: 'someProp', propValue: [{}] }; reducerTester() .givenReducer(variableEditorReducer, { ...initialVariableEditorState }) @@ -192,4 +193,18 @@ describe('variableEditorReducer', () => { }); }); }); + + describe('when cleanEditorState is dispatched', () => { + it('then state should be correct', () => { + reducerTester() + .givenReducer(variableEditorReducer, { + ...initialVariableEditorState, + isValid: false, + errors: { name: 'Name is an duplicate' }, + name: 'Duplicate name', + }) + .whenActionIsDispatched(cleanEditorState()) + .thenStateShouldEqual({ ...initialVariableEditorState }); + }); + }); }); diff --git a/public/app/features/variables/editor/reducer.ts b/public/app/features/variables/editor/reducer.ts index d38a16f11f0..e3caa2fd4cc 100644 --- a/public/app/features/variables/editor/reducer.ts +++ b/public/app/features/variables/editor/reducer.ts @@ -70,6 +70,7 @@ const variableEditorReducerSlice = createSlice({ [action.payload.propName]: action.payload.propValue, }; }, + cleanEditorState: () => initialVariableEditorState, }, }); @@ -85,4 +86,5 @@ export const { changeVariableEditorExtended, addVariableEditorError, removeVariableEditorError, + cleanEditorState, } = variableEditorReducerSlice.actions; diff --git a/public/app/features/variables/pickers/OptionsPicker/reducer.test.ts b/public/app/features/variables/pickers/OptionsPicker/reducer.test.ts index d88d08c95fc..7bf91076128 100644 --- a/public/app/features/variables/pickers/OptionsPicker/reducer.test.ts +++ b/public/app/features/variables/pickers/OptionsPicker/reducer.test.ts @@ -1,5 +1,6 @@ import { cloneDeep } from 'lodash'; import { + cleanPickerState, hideOptions, initialState as optionsPickerInitialState, moveOptionsHighlight, @@ -941,4 +942,22 @@ describe('optionsPickerReducer', () => { }); }); }); + + describe('when cleanPickerState is dispatched', () => { + it('then state should be correct', () => { + const { initialState } = getVariableTestContext({ + highlightIndex: 19, + multi: true, + id: 'some id', + options: [{ text: 'A', value: 'A', selected: true }], + queryValue: 'a query value', + selectedValues: [{ text: 'A', value: 'A', selected: true }], + }); + + reducerTester() + .givenReducer(optionsPickerReducer, cloneDeep(initialState)) + .whenActionIsDispatched(cleanPickerState()) + .thenStateShouldEqual({ ...optionsPickerInitialState }); + }); + }); }); diff --git a/public/app/features/variables/pickers/OptionsPicker/reducer.ts b/public/app/features/variables/pickers/OptionsPicker/reducer.ts index 6c6a72dc4a2..3178c56ba3c 100644 --- a/public/app/features/variables/pickers/OptionsPicker/reducer.ts +++ b/public/app/features/variables/pickers/OptionsPicker/reducer.ts @@ -252,6 +252,7 @@ const optionsPickerSlice = createSlice({ return applyStateChanges(state, updateDefaultSelection, updateOptions); }, + cleanPickerState: () => initialState, }, }); @@ -265,6 +266,7 @@ export const { updateSearchQuery, updateOptionsAndFilter, updateOptionsFromSearch, + cleanPickerState, } = optionsPickerSlice.actions; export const optionsPickerReducer = optionsPickerSlice.reducer; diff --git a/public/app/features/variables/state/actions.test.ts b/public/app/features/variables/state/actions.test.ts index 1b83eeeecf0..e838f6a3b87 100644 --- a/public/app/features/variables/state/actions.test.ts +++ b/public/app/features/variables/state/actions.test.ts @@ -45,6 +45,7 @@ import { changeVariableName } from '../editor/actions'; import { changeVariableNameFailed, changeVariableNameSucceeded, + cleanEditorState, initialVariableEditorState, setIdInEditor, } from '../editor/reducer'; @@ -55,7 +56,7 @@ import { variablesCompleteTransaction, variablesInitTransaction, } from './transactionReducer'; -import { initialState } from '../pickers/OptionsPicker/reducer'; +import { cleanPickerState, initialState } from '../pickers/OptionsPicker/reducer'; import { cleanVariables } from './variablesReducer'; import { expect } from '../../../../test/lib/common'; import { ConstantVariableModel, VariableRefresh } from '../types'; @@ -612,21 +613,23 @@ describe('shared actions', () => { tester.thenDispatchedActionsPredicateShouldEqual((dispatchedActions) => { expect(dispatchedActions[0]).toEqual(cleanVariables()); - expect(dispatchedActions[1]).toEqual(variablesClearTransaction()); - expect(dispatchedActions[2]).toEqual(variablesInitTransaction({ uid })); - expect(dispatchedActions[3].type).toEqual(addVariable.type); - expect(dispatchedActions[3].payload.id).toEqual('__dashboard'); - expect(dispatchedActions[4].type).toEqual(addVariable.type); - expect(dispatchedActions[4].payload.id).toEqual('__org'); + expect(dispatchedActions[1]).toEqual(cleanEditorState()); + expect(dispatchedActions[2]).toEqual(cleanPickerState()); + expect(dispatchedActions[3]).toEqual(variablesClearTransaction()); + expect(dispatchedActions[4]).toEqual(variablesInitTransaction({ uid })); expect(dispatchedActions[5].type).toEqual(addVariable.type); - expect(dispatchedActions[5].payload.id).toEqual('__user'); - expect(dispatchedActions[6]).toEqual( + expect(dispatchedActions[5].payload.id).toEqual('__dashboard'); + expect(dispatchedActions[6].type).toEqual(addVariable.type); + expect(dispatchedActions[6].payload.id).toEqual('__org'); + expect(dispatchedActions[7].type).toEqual(addVariable.type); + expect(dispatchedActions[7].payload.id).toEqual('__user'); + expect(dispatchedActions[8]).toEqual( addVariable(toVariablePayload(constant, { global: false, index: 0, model: constant })) ); - expect(dispatchedActions[7]).toEqual(variableStateNotStarted(toVariablePayload(constant))); - expect(dispatchedActions[8]).toEqual(variableStateCompleted(toVariablePayload(constant))); - expect(dispatchedActions[9]).toEqual(variablesCompleteTransaction({ uid })); - return dispatchedActions.length === 10; + expect(dispatchedActions[9]).toEqual(variableStateNotStarted(toVariablePayload(constant))); + expect(dispatchedActions[10]).toEqual(variableStateCompleted(toVariablePayload(constant))); + expect(dispatchedActions[11]).toEqual(variablesCompleteTransaction({ uid })); + return dispatchedActions.length === 12; }); }); }); @@ -638,7 +641,12 @@ describe('shared actions', () => { reduxTester<{ templating: TemplatingState }>() .givenRootReducer(getTemplatingRootReducer()) .whenActionIsDispatched(cleanUpVariables()) - .thenDispatchedActionsShouldEqual(cleanVariables(), variablesClearTransaction()); + .thenDispatchedActionsShouldEqual( + cleanVariables(), + cleanEditorState(), + cleanPickerState(), + variablesClearTransaction() + ); }); }); }); @@ -654,7 +662,12 @@ describe('shared actions', () => { reduxTester<{ templating: TemplatingState }>() .givenRootReducer(getTemplatingRootReducer()) .whenActionIsDispatched(cancelVariables({ getBackendSrv: () => backendSrvMock })) - .thenDispatchedActionsShouldEqual(cleanVariables(), variablesClearTransaction()); + .thenDispatchedActionsShouldEqual( + cleanVariables(), + cleanEditorState(), + cleanPickerState(), + variablesClearTransaction() + ); expect(cancelAllInFlightRequestsMock).toHaveBeenCalledTimes(1); }); diff --git a/public/app/features/variables/state/actions.ts b/public/app/features/variables/state/actions.ts index dfd4e9ff916..a67aff8daf1 100644 --- a/public/app/features/variables/state/actions.ts +++ b/public/app/features/variables/state/actions.ts @@ -55,6 +55,8 @@ import isEqual from 'lodash/isEqual'; import { getCurrentText, getVariableRefresh } from '../utils'; import { store } from 'app/store/store'; import { getDatasourceSrv } from '../../plugins/datasource_srv'; +import { cleanEditorState } from '../editor/reducer'; +import { cleanPickerState } from '../pickers/OptionsPicker/reducer'; // process flow queryVariable // thunk => processVariables @@ -621,6 +623,8 @@ export const initVariablesTransaction = (dashboardUid: string, dashboard: Dashbo export const cleanUpVariables = (): ThunkResult => (dispatch) => { dispatch(cleanVariables()); + dispatch(cleanEditorState()); + dispatch(cleanPickerState()); dispatch(variablesClearTransaction()); };