diff --git a/public/app/features/variables/editor/actions.test.ts b/public/app/features/variables/editor/actions.test.ts index 3358811bc6b..755259d977f 100644 --- a/public/app/features/variables/editor/actions.test.ts +++ b/public/app/features/variables/editor/actions.test.ts @@ -1,5 +1,14 @@ +import { variableAdapters } from '../adapters'; +import { initialConstantVariableModelState } from '../constant/reducer'; import { constantBuilder, customBuilder } from '../shared/testing/builders'; -import { getNextAvailableId } from './actions'; +import { initialKeyedVariablesState, toKeyedAction } from '../state/keyedVariablesReducer'; +import * as selectors from '../state/selectors'; +import * as inspectUtils from '../inspect/utils'; +import { addVariable } from '../state/sharedReducer'; +import { createConstantVariableAdapter } from '../constant/adapter'; +import { getNextAvailableId, switchToListMode, switchToNewMode } from './actions'; +import { setIdInEditor } from './reducer'; +import { initialState } from '../../dashboard/state/reducers'; describe('getNextAvailableId', () => { describe('when called with a custom type and there is already 2 variables', () => { @@ -15,3 +24,40 @@ describe('getNextAvailableId', () => { }); }); }); + +describe('switchToNewMode', () => { + variableAdapters.setInit(() => [createConstantVariableAdapter()]); + + it('should dispatch with the correct rootStateKey', () => { + jest.spyOn(selectors, 'getVariablesByKey').mockReturnValue([]); + jest.spyOn(selectors, 'getNewVariableIndex').mockReturnValue(0); + const mockId = 'constant0'; + const mockGetState = jest.fn().mockReturnValue({ templating: initialKeyedVariablesState }); + const mockDispatch = jest.fn(); + const model = { ...initialConstantVariableModelState, name: mockId, id: mockId, rootStateKey: 'null' }; + + switchToNewMode(null, 'constant')(mockDispatch, mockGetState, undefined); + expect(mockDispatch).toHaveBeenCalledTimes(2); + expect(mockDispatch.mock.calls[0][0]).toEqual( + toKeyedAction('null', addVariable({ data: { global: false, index: 0, model }, type: 'constant', id: mockId })) + ); + expect(mockDispatch.mock.calls[1][0]).toEqual(toKeyedAction('null', setIdInEditor({ id: mockId }))); + }); +}); + +describe('switchToListMode', () => { + variableAdapters.setInit(() => [createConstantVariableAdapter()]); + + it('should dispatch with the correct rootStateKey', () => { + jest.spyOn(selectors, 'getEditorVariables').mockReturnValue([]); + jest.spyOn(inspectUtils, 'createUsagesNetwork').mockReturnValue({ usages: [], unUsed: [] }); + jest.spyOn(inspectUtils, 'transformUsagesToNetwork').mockReturnValue([]); + const mockGetState = jest.fn().mockReturnValue({ templating: initialKeyedVariablesState, dashboard: initialState }); + const mockDispatch = jest.fn(); + + switchToListMode(null)(mockDispatch, mockGetState, undefined); + expect(mockDispatch).toHaveBeenCalledTimes(2); + expect(mockDispatch.mock.calls[0][0]).toEqual(toKeyedAction('null', expect.any(Object))); + expect(mockDispatch.mock.calls[1][0]).toEqual(toKeyedAction('null', expect.any(Object))); + }); +}); diff --git a/public/app/features/variables/editor/actions.ts b/public/app/features/variables/editor/actions.ts index 55d9b12c2a4..00d92fe1ffc 100644 --- a/public/app/features/variables/editor/actions.ts +++ b/public/app/features/variables/editor/actions.ts @@ -1,5 +1,16 @@ +import { VariableType } from '@grafana/data'; +import { cloneDeep } from 'lodash'; import { ThunkResult } from '../../../types'; +import { variableAdapters } from '../adapters'; +import { initInspect } from '../inspect/reducer'; +import { createUsagesNetwork, transformUsagesToNetwork } from '../inspect/utils'; +import { updateOptions } from '../state/actions'; +import { toKeyedAction } from '../state/keyedVariablesReducer'; import { getEditorVariables, getNewVariableIndex, getVariable, getVariablesByKey } from '../state/selectors'; +import { addVariable, removeVariable } from '../state/sharedReducer'; +import { AddVariable, KeyedVariableIdentifier, VariableIdentifier } from '../state/types'; +import { VariableModel } from '../types'; +import { toKeyedVariableIdentifier, toStateKey, toVariablePayload } from '../utils'; import { changeVariableNameFailed, changeVariableNameSucceeded, @@ -8,17 +19,6 @@ import { variableEditorMounted, variableEditorUnMounted, } from './reducer'; -import { variableAdapters } from '../adapters'; -import { AddVariable, KeyedVariableIdentifier, VariableIdentifier } from '../state/types'; -import { cloneDeep } from 'lodash'; -import { VariableType } from '@grafana/data'; -import { addVariable, removeVariable } from '../state/sharedReducer'; -import { updateOptions } from '../state/actions'; -import { VariableModel } from '../types'; -import { initInspect } from '../inspect/reducer'; -import { createUsagesNetwork, transformUsagesToNetwork } from '../inspect/utils'; -import { toKeyedAction } from '../state/keyedVariablesReducer'; -import { toKeyedVariableIdentifier, toVariablePayload } from '../utils'; export const variableEditorMount = (identifier: KeyedVariableIdentifier): ThunkResult => { return async (dispatch) => { @@ -92,18 +92,21 @@ export const completeChangeVariableName = }; export const switchToNewMode = - (key: string, type: VariableType = 'query'): ThunkResult => + (key: string | null | undefined, type: VariableType = 'query'): ThunkResult => (dispatch, getState) => { - const id = getNextAvailableId(type, getVariablesByKey(key, getState())); + const rootStateKey = toStateKey(key); + const id = getNextAvailableId(type, getVariablesByKey(rootStateKey, getState())); const identifier: VariableIdentifier = { type, id }; const global = false; - const index = getNewVariableIndex(key, getState()); + const index = getNewVariableIndex(rootStateKey, getState()); const model: VariableModel = cloneDeep(variableAdapters.get(type).initialState); model.id = id; model.name = id; - model.rootStateKey = key; - dispatch(toKeyedAction(key, addVariable(toVariablePayload(identifier, { global, model, index })))); - dispatch(toKeyedAction(key, setIdInEditor({ id: identifier.id }))); + model.rootStateKey = rootStateKey; + dispatch( + toKeyedAction(rootStateKey, addVariable(toVariablePayload(identifier, { global, model, index }))) + ); + dispatch(toKeyedAction(rootStateKey, setIdInEditor({ id: identifier.id }))); }; export const switchToEditMode = @@ -114,16 +117,17 @@ export const switchToEditMode = }; export const switchToListMode = - (key: string): ThunkResult => + (key: string | null | undefined): ThunkResult => (dispatch, getState) => { - dispatch(toKeyedAction(key, clearIdInEditor())); + const rootStateKey = toStateKey(key); + dispatch(toKeyedAction(rootStateKey, clearIdInEditor())); const state = getState(); - const variables = getEditorVariables(key, state); + const variables = getEditorVariables(rootStateKey, state); const dashboard = state.dashboard.getModel(); const { usages } = createUsagesNetwork(variables, dashboard); const usagesNetwork = transformUsagesToNetwork(usages); - dispatch(toKeyedAction(key, initInspect({ usages, usagesNetwork }))); + dispatch(toKeyedAction(rootStateKey, initInspect({ usages, usagesNetwork }))); }; export function getNextAvailableId(type: VariableType, variables: VariableModel[]): string {