Commit f47b7230 by Dominik Prokop Committed by GitHub

Make value mappings correctly interpret numeric-like strings (#30893)

* Make value mappings corectly interprete numeric-like strings

* More tests

* Update packages/grafana-data/src/utils/valueMappings.ts

* Update packages/grafana-data/src/utils/valueMappings.ts

Co-authored-by: Hugo Häggmark <hugo.haggmark@grafana.com>

* Fix issue detected by singlestat test

Co-authored-by: Hugo Häggmark <hugo.haggmark@grafana.com>
parent 32eb0019
import { getMappedValue } from './valueMappings';
import { getMappedValue, isNumeric } from './valueMappings';
import { ValueMapping, MappingType } from '../types';
describe('Format value with value mappings', () => {
......@@ -79,6 +79,7 @@ describe('Format value with value mappings', () => {
expect(getMappedValue(valueMappings, value).text).toEqual('1-20');
});
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' },
......@@ -89,4 +90,64 @@ describe('Format value with value mappings', () => {
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);
});
});
......@@ -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;
}
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));
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment