diff --git a/public/app/features/variables/query/reducer.test.ts b/public/app/features/variables/query/reducer.test.ts index 0dfe56651a9..c1452f0a130 100644 --- a/public/app/features/variables/query/reducer.test.ts +++ b/public/app/features/variables/query/reducer.test.ts @@ -1,6 +1,6 @@ import { reducerTester } from '../../../../test/core/redux/reducerTester'; -import { queryVariableReducer, updateVariableOptions, updateVariableTags } from './reducer'; -import { QueryVariableModel } from '../types'; +import { 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'; @@ -260,6 +260,28 @@ describe('queryVariableReducer', () => { }); }); +describe('sortVariableValues', () => { + describe('when using any sortOrder with an option with null as text', () => { + it.each` + options | sortOrder | expected + ${[{ text: '1' }, { text: null }, { text: '2' }]} | ${VariableSort.disabled} | ${[{ text: '1' }, { text: null }, { text: '2' }]} + ${[{ text: 'a' }, { text: null }, { text: 'b' }]} | ${VariableSort.alphabeticalAsc} | ${[{ text: 'a' }, { text: 'b' }, { text: null }]} + ${[{ text: 'a' }, { text: null }, { text: 'b' }]} | ${VariableSort.alphabeticalDesc} | ${[{ text: null }, { text: 'b' }, { text: 'a' }]} + ${[{ text: '1' }, { text: null }, { text: '2' }]} | ${VariableSort.numericalAsc} | ${[{ text: null }, { text: '1' }, { text: '2' }]} + ${[{ text: '1' }, { text: null }, { text: '2' }]} | ${VariableSort.numericalDesc} | ${[{ text: '2' }, { text: '1' }, { text: null }]} + ${[{ text: 'a' }, { text: null }, { text: 'b' }]} | ${VariableSort.alphabeticalCaseInsensitiveAsc} | ${[{ text: null }, { text: 'a' }, { text: 'b' }]} + ${[{ text: 'a' }, { text: null }, { text: 'b' }]} | ${VariableSort.alphabeticalCaseInsensitiveDesc} | ${[{ text: 'b' }, { text: 'a' }, { text: null }]} + `( + 'then it should sort the options correctly without throwing (sortOrder:$sortOrder)', + ({ options, sortOrder, expected }) => { + const result = sortVariableValues(options, sortOrder); + + 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 b20ab327a9b..ea1a81e9aed 100644 --- a/public/app/features/variables/query/reducer.ts +++ b/public/app/features/variables/query/reducer.ts @@ -52,7 +52,7 @@ export const initialQueryVariableModelState: QueryVariableModel = { definition: '', }; -const sortVariableValues = (options: any[], sortOrder: VariableSort) => { +export const sortVariableValues = (options: any[], sortOrder: VariableSort) => { if (sortOrder === VariableSort.disabled) { return options; } @@ -64,6 +64,10 @@ const sortVariableValues = (options: any[], sortOrder: VariableSort) => { options = _.sortBy(options, 'text'); } else if (sortType === 2) { options = _.sortBy(options, opt => { + if (!opt.text) { + return -1; + } + const matches = opt.text.match(/.*?(\d+).*/); if (!matches || matches.length < 2) { return -1;