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>
This commit is contained in:
co-authored by
Hugo Häggmark
parent
32eb001919
commit
f47b72304c
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user