diff --git a/public/app/features/variables/query/reducer.test.ts b/public/app/features/variables/query/reducer.test.ts index c1452f0a130..73efcf43cf0 100644 --- a/public/app/features/variables/query/reducer.test.ts +++ b/public/app/features/variables/query/reducer.test.ts @@ -1,12 +1,18 @@ import { reducerTester } from '../../../../test/core/redux/reducerTester'; -import { queryVariableReducer, sortVariableValues, updateVariableOptions, updateVariableTags } from './reducer'; +import { + getAllMatches, + queryVariableReducer, + sortVariableValues, + updateVariableOptions, + updateVariableTags, +} from './reducer'; import { QueryVariableModel, VariableSort } from '../types'; import cloneDeep from 'lodash/cloneDeep'; import { VariablesState } from '../state/variablesReducer'; import { getVariableTestContext } from '../state/helpers'; import { toVariablePayload } from '../state/types'; import { createQueryVariableAdapter } from './adapter'; -import { MetricFindValue } from '@grafana/data'; +import { MetricFindValue, stringToJsRegex } from '@grafana/data'; describe('queryVariableReducer', () => { const adapter = createQueryVariableAdapter(); @@ -218,6 +224,25 @@ describe('queryVariableReducer', () => { }); }); + it('unnamed capture group returns any unnamed match', () => { + const regex = '/.*_(\\w+)\\{/gi'; + const { initialState } = getVariableTestContext(adapter, { includeAll: false, regex }); + const metrics = [createMetric('instance_counter{someother="atext",something="avalue"}'), createMetric('B')]; + const update = { results: metrics, templatedRegex: regex }; + const payload = toVariablePayload({ id: '0', type: 'query' }, update); + + reducerTester() + .givenReducer(queryVariableReducer, cloneDeep(initialState)) + .whenActionIsDispatched(updateVariableOptions(payload)) + .thenStateShouldEqual({ + ...initialState, + '0': ({ + ...initialState[0], + options: [{ text: 'counter', value: 'counter', selected: false }], + } as unknown) as QueryVariableModel, + }); + }); + it('unmatched text capture and unmatched value capture returns empty state', () => { const regex = '/somevalue="(?[^"]+)|somelabel="(?[^"]+)/gi'; const { initialState } = getVariableTestContext(adapter, { includeAll: false, regex }); @@ -282,6 +307,41 @@ describe('sortVariableValues', () => { }); }); +describe('getAllMatches', () => { + it.each` + str | regex | expected + ${'A{somelabel="atext",somevalue="avalue"}'} | ${'/unknown/gi'} | ${{}} + ${'A{somelabel="atext",somevalue="avalue"}'} | ${'/unknown/i'} | ${{}} + ${'A{somelabel="atext",somevalue="avalue"}'} | ${'/some(\\w+)/gi'} | ${{ 0: 'somevalue', 1: 'value', index: 20, input: 'A{somelabel="atext",somevalue="avalue"}' }} + ${'A{somelabel="atext",somevalue="avalue"}'} | ${'/some(\\w+)/i'} | ${{ 0: 'somelabel', 1: 'label', index: 2, input: 'A{somelabel="atext",somevalue="avalue"}' }} + ${'A{somelabel="atext",somevalue="avalue"}'} | ${'/somevalue="(?[^"]+)|somelabel="(?[^"]+)/gi'} | ${{ + 0: 'somevalue="avalue', + 1: 'avalue', + 2: 'atext', + groups: { + text: 'atext', + value: 'avalue', + }, + index: 20, + input: 'A{somelabel="atext",somevalue="avalue"}', +}} + ${'A{somelabel="atext",somevalue="avalue"}'} | ${'/somevalue="(?[^"]+)|somelabel="(?[^"]+)/i'} | ${{ + 0: 'somelabel="atext', + 1: undefined, + 2: 'atext', + groups: { + text: 'atext', + }, + index: 2, + input: 'A{somelabel="atext",somevalue="avalue"}', +}} + `('when called with str:{$str}, regex:{$regex} then it should return correct matches', ({ str, regex, expected }) => { + const result = getAllMatches(str, stringToJsRegex(regex)); + + expect(result).toEqual(expected); + }); +}); + function createMetric(value: string) { return { text: value, diff --git a/public/app/features/variables/query/reducer.ts b/public/app/features/variables/query/reducer.ts index 8c8160ce1b2..4513e7e6d78 100644 --- a/public/app/features/variables/query/reducer.ts +++ b/public/app/features/variables/query/reducer.ts @@ -88,7 +88,7 @@ export const sortVariableValues = (options: any[], sortOrder: VariableSort) => { return options; }; -const getAllMatches = (str: string, regex: RegExp): any => { +export const getAllMatches = (str: string, regex: RegExp): any => { const results = {}; let matches; @@ -139,6 +139,7 @@ const metricNamesToVariableValues = (variableRegEx: string, sort: VariableSort, text = matches.groups.text; value = text; } else if (matches['1']) { + text = matches['1']; value = matches['1']; } }