diff --git a/packages/grafana-data/src/utils/valueMappings.test.ts b/packages/grafana-data/src/utils/valueMappings.test.ts index eee48dbe5e3..e6bf474f76c 100644 --- a/packages/grafana-data/src/utils/valueMappings.test.ts +++ b/packages/grafana-data/src/utils/valueMappings.test.ts @@ -1,4 +1,4 @@ -import { getMappedValue } from './valueMappings'; +import { getMappedValue, isNumeric } from './valueMappings'; import { ValueMapping, MappingType } from '../types'; describe('Format value with value mappings', () => { @@ -79,14 +79,75 @@ describe('Format value with value mappings', () => { expect(getMappedValue(valueMappings, value).text).toEqual('1-20'); }); - it('should map value text to mapping', () => { - const valueMappings: ValueMapping[] = [ - { id: 0, text: '1-20', type: MappingType.RangeToText, from: '1', to: '20' }, - { id: 1, text: 'ELVA', type: MappingType.ValueToText, value: 'elva' }, - ]; + describe('text mapping', () => { + it('should map value text to mapping', () => { + const valueMappings: ValueMapping[] = [ + { id: 0, text: '1-20', type: MappingType.RangeToText, from: '1', to: '20' }, + { id: 1, text: 'ELVA', type: MappingType.ValueToText, value: 'elva' }, + ]; - const value = 'elva'; + const value = 'elva'; - expect(getMappedValue(valueMappings, value).text).toEqual('ELVA'); + expect(getMappedValue(valueMappings, value).text).toEqual('ELVA'); + }); + + it.each` + value | expected + ${'2/0/12'} | ${{ id: 1, text: 'mapped value 1', type: MappingType.ValueToText, value: '2/0/12' }} + ${'2/1/12'} | ${undefined} + ${'2:0'} | ${{ id: 3, text: 'mapped value 3', type: MappingType.ValueToText, value: '2:0' }} + ${'2:1'} | ${undefined} + ${'20whatever'} | ${{ id: 2, text: 'mapped value 2', type: MappingType.ValueToText, value: '20whatever' }} + ${'20whateve'} | ${undefined} + ${'20'} | ${undefined} + ${'00020.4'} | ${undefined} + ${'192.168.1.1'} | ${{ id: 4, text: 'mapped value ip', type: MappingType.ValueToText, value: '192.168.1.1' }} + ${'192'} | ${undefined} + ${'192.168'} | ${undefined} + ${'192.168.1'} | ${undefined} + ${'9.90'} | ${{ id: 5, text: 'OK', type: MappingType.ValueToText, value: '9.9' }} + `('numeric-like text mapping, value:${value', ({ value, expected }) => { + const valueMappings: ValueMapping[] = [ + { id: 1, text: 'mapped value 1', type: MappingType.ValueToText, value: '2/0/12' }, + { id: 2, text: 'mapped value 2', type: MappingType.ValueToText, value: '20whatever' }, + { id: 3, text: 'mapped value 3', type: MappingType.ValueToText, value: '2:0' }, + { id: 4, text: 'mapped value ip', type: MappingType.ValueToText, value: '192.168.1.1' }, + { id: 5, text: 'OK', type: MappingType.ValueToText, value: '9.9' }, + ]; + expect(getMappedValue(valueMappings, value)).toEqual(expected); + }); + }); +}); + +describe('isNumeric', () => { + it.each` + value | expected + ${123} | ${true} + ${'123'} | ${true} + ${' 123'} | ${true} + ${' 123 '} | ${true} + ${-123.4} | ${true} + ${'-123.4'} | ${true} + ${0.41} | ${true} + ${'.41'} | ${true} + ${0x12} | ${true} + ${'0x12'} | ${true} + ${'000123.4'} | ${true} + ${2e64} | ${true} + ${'2e64'} | ${true} + ${1e10000} | ${true} + ${'1e10000'} | ${true} + ${Infinity} | ${true} + ${'abc'} | ${false} + ${' '} | ${false} + ${null} | ${false} + ${undefined} | ${false} + ${NaN} | ${false} + ${''} | ${false} + ${{}} | ${false} + ${true} | ${false} + ${[]} | ${false} + `('detects numeric values', ({ value, expected }) => { + expect(isNumeric(value)).toEqual(expected); }); }); diff --git a/packages/grafana-data/src/utils/valueMappings.ts b/packages/grafana-data/src/utils/valueMappings.ts index 8aa3f9061da..e7b2721784f 100644 --- a/packages/grafana-data/src/utils/valueMappings.ts +++ b/packages/grafana-data/src/utils/valueMappings.ts @@ -15,20 +15,23 @@ const addValueToTextMappingText = ( return allValueMappings.concat(valueToTextMapping); } - const valueAsNumber = parseFloat(value as string); - const valueToTextMappingAsNumber = parseFloat(valueToTextMapping.value as string); + let valueAsNumber, valueToTextMappingAsNumber; - if (isNaN(valueAsNumber) || isNaN(valueToTextMappingAsNumber)) { - if (value === valueToTextMapping.value) { + if (isNumeric(value as string) && isNumeric(valueToTextMapping.value)) { + valueAsNumber = parseFloat(value as string); + valueToTextMappingAsNumber = parseFloat(valueToTextMapping.value as string); + + if (valueAsNumber === valueToTextMappingAsNumber) { return allValueMappings.concat(valueToTextMapping); } - } - - if (valueAsNumber !== valueToTextMappingAsNumber) { return allValueMappings; } - return allValueMappings.concat(valueToTextMapping); + if (value === valueToTextMapping.value) { + return allValueMappings.concat(valueToTextMapping); + } + + return allValueMappings; }; const addRangeToTextMappingText = ( @@ -93,3 +96,12 @@ const isNullValueMap = (mapping: ValueMap): boolean => { } return mapping.value.toLowerCase() === 'null'; }; + +// Ref https://stackoverflow.com/a/42356340 +export function isNumeric(num: any) { + if (num === true) { + return false; + } + + return Boolean(Number(num)); +}