diff --git a/public/app/plugins/datasource/graphite/specs/store.test.ts b/public/app/plugins/datasource/graphite/specs/store.test.ts index 68deeaeb6cd..0a5ab8ba57e 100644 --- a/public/app/plugins/datasource/graphite/specs/store.test.ts +++ b/public/app/plugins/datasource/graphite/specs/store.test.ts @@ -341,19 +341,23 @@ describe('Graphite actions', async () => { }); }); - describe('when updating target used in other query', () => { + describe('target interpolation', () => { beforeEach(async () => { ctx.datasource.metricFindQuery = () => Promise.resolve([{ expandable: false }]); ctx.state.target.refId = 'A'; - await changeTarget(ctx, 'metrics.foo.count'); - - ctx.state.queries = [ctx.state.target, { target: 'sumSeries(#A)', refId: 'B' }]; - - await changeTarget(ctx, 'metrics.bar.count'); + await changeTarget(ctx, 'sumSeries(#B)'); }); - it('targetFull of other query should update', () => { - expect(ctx.state.queries[1].targetFull).toBe('sumSeries(metrics.bar.count)'); + it('when updating target used in other query, targetFull of other query should update', async () => { + ctx.state.queries = [ctx.state.target, { target: 'metrics.foo.count', refId: 'B' }]; + await changeTarget(ctx, 'sumSeries(#B)'); + expect(ctx.state.queryModel.target.targetFull).toBe('sumSeries(metrics.foo.count)'); + }); + + it('when updating target from a query from other data source, targetFull of other query should not update', async () => { + ctx.state.queries = [ctx.state.target, { someOtherProperty: 'metrics.foo.count', refId: 'B' }]; + await changeTarget(ctx, 'sumSeries(#B)'); + expect(ctx.state.queryModel.target.targetFull).toBeUndefined(); }); }); diff --git a/public/app/plugins/datasource/graphite/state/helpers.ts b/public/app/plugins/datasource/graphite/state/helpers.ts index a5071fc38dc..49474f6c56e 100644 --- a/public/app/plugins/datasource/graphite/state/helpers.ts +++ b/public/app/plugins/datasource/graphite/state/helpers.ts @@ -4,7 +4,7 @@ import { dispatch } from '../../../../store/store'; import { notifyApp } from '../../../../core/reducers/appNotification'; import { createErrorNotification } from '../../../../core/copy/appNotification'; import { FuncInstance } from '../gfunc'; -import { GraphiteTagOperator } from '../types'; +import { GraphiteQuery, GraphiteTagOperator } from '../types'; /** * Helpers used by reducers and providers. They modify state object directly so should operate on a copy of the state. @@ -152,7 +152,13 @@ export function handleTargetChanged(state: GraphiteQueryEditorState): void { } const oldTarget = state.queryModel.target.target; - state.queryModel.updateModelTarget(state.queries); + // Interpolate from other queries: + // Because of mixed data sources the list may contain queries for non-Graphite data sources. To ensure a valid query + // is used for interpolation we should check required properties are passed though in theory it allows to interpolate + // with queries that contain "target" property as well. + state.queryModel.updateModelTarget( + (state.queries || []).filter((query) => 'target' in query && typeof (query as GraphiteQuery).target === 'string') + ); if (state.queryModel.target.target !== oldTarget && !state.paused) { state.refresh(state.target.target);