diff --git a/public/app/features/variables/state/actions.ts b/public/app/features/variables/state/actions.ts index 054e9b35dde..7a692804025 100644 --- a/public/app/features/variables/state/actions.ts +++ b/public/app/features/variables/state/actions.ts @@ -52,6 +52,7 @@ import { hasOptions, hasStandardVariableSupport, isAdHoc, + isConstant, isMulti, isQuery, } from '../guard'; @@ -628,6 +629,10 @@ export const templateVarsChangedInUrl = ( if (variableInModel && hasCurrent(variableInModel)) { value = variableInModel.current.value; // revert value to the value stored in dashboard json } + + if (variableInModel && isConstant(variableInModel)) { + value = variableInModel.query; // revert value to the value stored in dashboard json, constants don't store current values in dashboard json + } } const promise = variableAdapters.get(variable.type).setValueFromUrl(variable, value); diff --git a/public/app/features/variables/state/templateVarsChangedInUrl.test.ts b/public/app/features/variables/state/templateVarsChangedInUrl.test.ts index 248c21123d2..3ea902fec4d 100644 --- a/public/app/features/variables/state/templateVarsChangedInUrl.test.ts +++ b/public/app/features/variables/state/templateVarsChangedInUrl.test.ts @@ -1,5 +1,5 @@ import { variableAdapters } from '../adapters'; -import { customBuilder } from '../shared/testing/builders'; +import { constantBuilder, customBuilder } from '../shared/testing/builders'; import { DashboardState, StoreState } from '../../../types'; import { initialState } from '../../dashboard/state/reducers'; import { TemplatingState } from './reducers'; @@ -8,17 +8,27 @@ import { templateVarsChangedInUrl } from './actions'; import { createCustomVariableAdapter } from '../custom/adapter'; import { VariablesState } from './types'; import { DashboardModel } from '../../dashboard/state'; +import { createConstantVariableAdapter } from '../constant/adapter'; +import { VariableModel } from '../types'; const dashboardModel = new DashboardModel({}); -variableAdapters.setInit(() => [createCustomVariableAdapter()]); +variableAdapters.setInit(() => [createCustomVariableAdapter(), createConstantVariableAdapter()]); -async function getTestContext(urlQueryMap: ExtendedUrlQueryMap = {}) { +async function getTestContext(urlQueryMap: ExtendedUrlQueryMap = {}, variable: VariableModel | undefined = undefined) { jest.clearAllMocks(); - const custom = customBuilder().withId('custom').withCurrent(['A', 'C']).withOptions('A', 'B', 'C').build(); + if (!variable) { + variable = customBuilder() + .withId('variable') + .withName('variable') + .withCurrent(['A', 'C']) + .withOptions('A', 'B', 'C') + .build(); + } + const setValueFromUrlMock = jest.fn(); - variableAdapters.get('custom').setValueFromUrl = setValueFromUrlMock; + variableAdapters.get(variable.type).setValueFromUrl = setValueFromUrlMock; const templateVariableValueUpdatedMock = jest.fn(); const startRefreshMock = jest.fn(); @@ -27,12 +37,12 @@ async function getTestContext(urlQueryMap: ExtendedUrlQueryMap = {}) { getModel: () => { dashboardModel.templateVariableValueUpdated = templateVariableValueUpdatedMock; dashboardModel.startRefresh = startRefreshMock; - dashboardModel.templating = { list: [custom] }; + dashboardModel.templating = { list: [variable] }; return dashboardModel; }, }; - const variables: VariablesState = { custom }; + const variables: VariablesState = { variable }; const templating = ({ variables } as unknown) as TemplatingState; const state: Partial = { dashboard, @@ -45,7 +55,7 @@ async function getTestContext(urlQueryMap: ExtendedUrlQueryMap = {}) { await thunk(dispatch, getState, undefined); - return { setValueFromUrlMock, templateVariableValueUpdatedMock, startRefreshMock, custom }; + return { setValueFromUrlMock, templateVariableValueUpdatedMock, startRefreshMock, variable }; } describe('templateVarsChangedInUrl', () => { @@ -75,7 +85,7 @@ describe('templateVarsChangedInUrl', () => { describe('and the values in url query map are the same as current in state', () => { it('then no value should change and dashboard should not be refreshed', async () => { const { setValueFromUrlMock, templateVariableValueUpdatedMock, startRefreshMock } = await getTestContext({ - 'var-custom': { value: ['A', 'C'] }, + 'var-variable': { value: ['A', 'C'] }, }); expect(setValueFromUrlMock).not.toHaveBeenCalled(); @@ -90,13 +100,13 @@ describe('templateVarsChangedInUrl', () => { setValueFromUrlMock, templateVariableValueUpdatedMock, startRefreshMock, - custom, + variable, } = await getTestContext({ - 'var-custom': { value: 'B' }, + 'var-variable': { value: 'B' }, }); expect(setValueFromUrlMock).toHaveBeenCalledTimes(1); - expect(setValueFromUrlMock).toHaveBeenCalledWith(custom, 'B'); + expect(setValueFromUrlMock).toHaveBeenCalledWith(variable, 'B'); expect(templateVariableValueUpdatedMock).toHaveBeenCalledTimes(1); expect(startRefreshMock).toHaveBeenCalledTimes(1); }); @@ -107,13 +117,39 @@ describe('templateVarsChangedInUrl', () => { setValueFromUrlMock, templateVariableValueUpdatedMock, startRefreshMock, - custom, + variable, } = await getTestContext({ - 'var-custom': { value: '', removed: true }, + 'var-variable': { value: '', removed: true }, }); expect(setValueFromUrlMock).toHaveBeenCalledTimes(1); - expect(setValueFromUrlMock).toHaveBeenCalledWith(custom, ['A', 'C']); + expect(setValueFromUrlMock).toHaveBeenCalledWith(variable, ['A', 'C']); + expect(templateVariableValueUpdatedMock).toHaveBeenCalledTimes(1); + expect(startRefreshMock).toHaveBeenCalledTimes(1); + }); + }); + + describe('and the variable is a constant', () => { + it('then the value should change to the value in dashboard json and dashboard should be refreshed', async () => { + const constant = constantBuilder() + .withId('variable') + .withName('variable') + .withQuery('default value in dash.json') + .build(); + const { + setValueFromUrlMock, + templateVariableValueUpdatedMock, + startRefreshMock, + variable, + } = await getTestContext( + { + 'var-variable': { value: '', removed: true }, + }, + constant + ); + + expect(setValueFromUrlMock).toHaveBeenCalledTimes(1); + expect(setValueFromUrlMock).toHaveBeenCalledWith(variable, 'default value in dash.json'); expect(templateVariableValueUpdatedMock).toHaveBeenCalledTimes(1); expect(startRefreshMock).toHaveBeenCalledTimes(1); });