Files
grafana/public/app/features/transformers/timeSeriesTable/timeSeriesTableTransformer.test.ts
Kyle Cunningham 71e3814c46 Transformations: Allow Timeseries to table transformation to handle multiple time series (#76801)
* Initial fix up of getLabelFields

* Update time series to table code

* Cleanup and allow merging

* Support merge and non-merge scenarios

* Update editor

* Fix case with merge true for multiple queries

* Update time series detection, fix tests

* Remove spurious console.log

* Prettier plus remove test console.log

* Remove type assertion

* Add options migration

* Add type export

* Sentence casing

* Make sure current options are preserved when making changes

* Add disabled image

* DashboardMigrator prettier

* Add type assertion explanation and exception

* Fix schema version test

* Prettier

* Fix genAI tests and make them more robust so they dont break on every new schema version

---------

Co-authored-by: nmarrs <nathanielmarrs@gmail.com>
2023-10-27 10:30:49 -05:00

136 lines
4.6 KiB
TypeScript

import { toDataFrame, FieldType, Labels, DataFrame, Field, ReducerID } from '@grafana/data';
import { timeSeriesToTableTransform } from './timeSeriesTableTransformer';
describe('timeSeriesTableTransformer', () => {
it('Will transform a single query', () => {
const series = [
getTimeSeries('A', { instance: 'A', pod: 'B' }),
getTimeSeries('A', { instance: 'A', pod: 'C' }),
getTimeSeries('A', { instance: 'A', pod: 'D' }),
];
const results = timeSeriesToTableTransform({}, series);
expect(results).toHaveLength(1);
const result = results[0];
expect(result.refId).toBe('A');
expect(result.fields).toHaveLength(3);
expect(result.fields[0].values).toEqual([
'Value : instance=A : pod=B',
'Value : instance=A : pod=C',
'Value : instance=A : pod=D',
]);
assertDataFrameField(result.fields[1], series);
});
it('Will pass through non time series frames', () => {
const series = [
getTable('B', ['foo', 'bar']),
getTimeSeries('A', { instance: 'A', pod: 'B' }),
getTimeSeries('A', { instance: 'A', pod: 'C' }),
getTable('C', ['bar', 'baz', 'bad']),
];
const results = timeSeriesToTableTransform({}, series);
expect(results).toHaveLength(3);
expect(results[0]).toEqual(series[0]);
expect(results[1].refId).toBe('A');
expect(results[1].fields).toHaveLength(3);
expect(results[2]).toEqual(series[3]);
});
it('Will group by refId', () => {
const series = [
getTimeSeries('A', { instance: 'A', pod: 'B' }),
getTimeSeries('A', { instance: 'A', pod: 'C' }),
getTimeSeries('A', { instance: 'A', pod: 'D' }),
getTimeSeries('B', { instance: 'B', pod: 'F', cluster: 'A' }),
getTimeSeries('B', { instance: 'B', pod: 'G', cluster: 'B' }),
];
const results = timeSeriesToTableTransform({}, series);
expect(results).toHaveLength(2);
expect(results[0].refId).toBe('A');
expect(results[0].fields).toHaveLength(3);
expect(results[0].fields[0].values).toEqual([
'Value : instance=A : pod=B',
'Value : instance=A : pod=C',
'Value : instance=A : pod=D',
]);
assertDataFrameField(results[0].fields[1], series.slice(0, 3));
expect(results[1].refId).toBe('B');
expect(results[1].fields).toHaveLength(3);
expect(results[1].fields[0].values).toEqual([
'Value : instance=B : pod=F : cluster=A',
'Value : instance=B : pod=G : cluster=B',
]);
expect(results[1].fields[0].values).toEqual([
'Value : instance=B : pod=F : cluster=A',
'Value : instance=B : pod=G : cluster=B',
]);
assertDataFrameField(results[1].fields[1], series.slice(3, 5));
});
it('Will include last value by deault', () => {
const series = [
getTimeSeries('A', { instance: 'A', pod: 'B' }, [4, 2, 3]),
getTimeSeries('A', { instance: 'A', pod: 'C' }, [3, 4, 5]),
];
const results = timeSeriesToTableTransform({}, series);
expect(results[0].fields[1].values[0].fields[1].values[2]).toEqual(3);
expect(results[0].fields[1].values[1].fields[1].values[2]).toEqual(5);
});
it('Will calculate average value if configured', () => {
const series = [
getTimeSeries('A', { instance: 'A', pod: 'B' }, [4, 2, 3]),
getTimeSeries('B', { instance: 'A', pod: 'C' }, [3, 4, 5]),
];
const results = timeSeriesToTableTransform({ B: { stat: ReducerID.mean } }, series);
expect(results[0].fields[2].values[0]).toEqual(3);
expect(results[1].fields[2].values[0]).toEqual(4);
});
});
function assertFieldsEqual(field1: Field, field2: Field) {
expect(field1.type).toEqual(field2.type);
expect(field1.name).toEqual(field2.name);
expect(field1.values).toEqual(field2.values);
expect(field1.labels ?? {}).toEqual(field2.labels ?? {});
}
function assertDataFrameField(field: Field, matchesFrames: DataFrame[]) {
const frames: DataFrame[] = field.values;
expect(frames).toHaveLength(matchesFrames.length);
frames.forEach((frame, idx) => {
const matchingFrame = matchesFrames[idx];
expect(frame.fields).toHaveLength(matchingFrame.fields.length);
frame.fields.forEach((field, fidx) => assertFieldsEqual(field, matchingFrame.fields[fidx]));
});
}
function getTimeSeries(refId: string, labels: Labels, values: number[] = [10]) {
return toDataFrame({
refId,
fields: [
{ name: 'Time', type: FieldType.time, values: [10] },
{
name: 'Value',
type: FieldType.number,
values,
labels,
},
],
});
}
function getTable(refId: string, fields: string[]) {
return toDataFrame({
refId,
fields: fields.map((f) => ({ name: f, type: FieldType.string, values: ['value'] })),
labels: {},
});
}