Transformations: Fill array with undefined to prevent mismatching length (#78911)

* fill array with `undefined` to prevent matching length

* update unit test to include sortBy transformation

---------

Co-authored-by: Galen <galen.kistler@grafana.com>
This commit is contained in:
Sven Grossmann
2023-12-01 20:33:05 +01:00
committed by GitHub
parent b64802ed3b
commit af05fdc806
2 changed files with 126 additions and 2 deletions

View File

@@ -1,5 +1,14 @@
import { DataFrame, Field, FieldType } from '@grafana/data';
import {
DataFrame,
DataTransformerConfig,
DataTransformerID,
Field,
FieldType,
transformDataFrame,
} from '@grafana/data';
import { toDataFrame } from '@grafana/data/src/dataframe/processDataFrame';
import { SortByTransformerOptions, sortByTransformer } from '@grafana/data/src/transformations/transformers/sortBy';
import { mockTransformationsRegistry } from '@grafana/data/src/utils/tests/mockTransformationsRegistry';
import { extractFieldsTransformer } from './extractFields';
import { ExtractFieldsOptions, FieldExtractorID } from './types';
@@ -233,6 +242,121 @@ describe('Fields from JSON', () => {
length: 2,
});
});
it('works with different value sizes', async () => {
const extractConfig: ExtractFieldsOptions = {
source: 'line',
replace: false,
};
const sortConfig: DataTransformerConfig<SortByTransformerOptions> = {
id: DataTransformerID.sortBy,
options: {
sort: [
{
field: 'time',
},
],
},
};
mockTransformationsRegistry([sortByTransformer]);
const ctx = { interpolate: (v: string) => v };
const testDataFrame: DataFrame = {
fields: [
{ config: {}, name: 'Time', type: FieldType.time, values: [1, 2] },
{ config: {}, name: 'line', type: FieldType.other, values: ['{"foo":"bar"}', '{"baz":"bar"}'] },
],
length: 2,
};
const expected = {
fields: [
{
config: {},
name: 'Time',
type: 'time',
values: [1, 2],
state: {
displayName: 'Time',
multipleFrames: false,
},
},
{
config: {},
name: 'line',
state: {
displayName: 'line',
multipleFrames: false,
},
type: 'other',
values: ['{"foo":"bar"}', '{"baz":"bar"}'],
},
{
name: 'foo',
state: {
displayName: 'foo',
multipleFrames: false,
},
values: ['bar', undefined],
type: 'string',
config: {},
},
{
name: 'baz',
state: {
displayName: 'baz',
multipleFrames: false,
},
values: [undefined, 'bar'],
type: 'string',
config: {},
},
],
length: 2,
meta: {
transformations: ['sortBy'],
},
};
const frames = extractFieldsTransformer.transformer(extractConfig, ctx)([testDataFrame]);
await expect(transformDataFrame([sortConfig], frames)).toEmitValuesWith((received) => {
expect(received[0][0].fields[2]).toMatchInlineSnapshot(`
{
"config": {},
"name": "foo",
"state": {
"displayName": "foo",
"multipleFrames": false,
},
"type": "string",
"values": [
"bar",
undefined,
],
}
`);
expect(received[0][0].fields[3]).toMatchInlineSnapshot(`
{
"config": {},
"name": "baz",
"state": {
"displayName": "baz",
"multipleFrames": false,
},
"type": "string",
"values": [
undefined,
"bar",
],
}
`);
});
expect(frames.length).toEqual(1);
expect(frames[0]).toEqual(expected);
});
});
const testFieldTime: Field = {

View File

@@ -86,7 +86,7 @@ export function addExtractedFields(frame: DataFrame, options: ExtractFieldsOptio
for (const [key, val] of Object.entries(obj)) {
let buffer = values.get(key);
if (buffer == null) {
buffer = new Array(count);
buffer = new Array(count).fill(undefined);
values.set(key, buffer);
names.push(key);
}