Logs: update tests
This commit is contained in:
@@ -6,6 +6,7 @@ import {
|
||||
mergeWithDefaults,
|
||||
hasLegacyColumns,
|
||||
extractColumnsValue,
|
||||
extractDisplayedFields,
|
||||
migrateLegacyColumns,
|
||||
} from './columnMigration';
|
||||
|
||||
@@ -186,104 +187,128 @@ describe('columnMigration', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('extractDisplayedFields', () => {
|
||||
it('should extract displayedFields array', () => {
|
||||
const state = { displayedFields: ['Time', 'level', 'host'] };
|
||||
expect(extractDisplayedFields(state)).toEqual(['Time', 'level', 'host']);
|
||||
});
|
||||
|
||||
it('should return undefined when displayedFields not present', () => {
|
||||
const state = { columns: ['Time'] };
|
||||
expect(extractDisplayedFields(state)).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should extract empty displayedFields array', () => {
|
||||
const state = { displayedFields: [] };
|
||||
expect(extractDisplayedFields(state)).toEqual([]);
|
||||
});
|
||||
|
||||
it('should handle state with both columns and displayedFields', () => {
|
||||
const state = {
|
||||
columns: { '0': 'cluster', '1': 'Line' },
|
||||
displayedFields: ['service_name', 'component'],
|
||||
};
|
||||
expect(extractDisplayedFields(state)).toEqual(['service_name', 'component']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('migrateLegacyColumns', () => {
|
||||
const defaultDisplayedFields = ['Time', LOG_LINE_BODY_FIELD_NAME];
|
||||
|
||||
it('should return null when logsState is null', () => {
|
||||
expect(migrateLegacyColumns(null, defaultDisplayedFields)).toBeNull();
|
||||
describe('general behavior', () => {
|
||||
it('should return null when logsState is null', () => {
|
||||
expect(migrateLegacyColumns(null, defaultDisplayedFields, 'table')).toBeNull();
|
||||
});
|
||||
|
||||
it('should return null when logsState is undefined', () => {
|
||||
expect(migrateLegacyColumns(undefined, defaultDisplayedFields, 'table')).toBeNull();
|
||||
});
|
||||
|
||||
it('should return null when no columns property exists', () => {
|
||||
const logsState = { displayedFields: ['Time'] };
|
||||
expect(migrateLegacyColumns(logsState, defaultDisplayedFields, 'table')).toBeNull();
|
||||
});
|
||||
|
||||
it('should return null when visualisationType is not provided', () => {
|
||||
const logsState = { columns: ['Time', 'level'] };
|
||||
expect(migrateLegacyColumns(logsState, defaultDisplayedFields)).toBeNull();
|
||||
});
|
||||
|
||||
it('should return null when visualisationType is unknown', () => {
|
||||
const logsState = { columns: ['Time', 'level'] };
|
||||
expect(migrateLegacyColumns(logsState, defaultDisplayedFields, 'unknown')).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return null when logsState is undefined', () => {
|
||||
expect(migrateLegacyColumns(undefined, defaultDisplayedFields)).toBeNull();
|
||||
});
|
||||
describe('visualisationType: table', () => {
|
||||
it('should return null when columns is empty array', () => {
|
||||
const logsState = { columns: [] };
|
||||
expect(migrateLegacyColumns(logsState, defaultDisplayedFields, 'table')).toBeNull();
|
||||
});
|
||||
|
||||
it('should return null when no columns property exists', () => {
|
||||
const logsState = { displayedFields: ['Time'] };
|
||||
expect(migrateLegacyColumns(logsState, defaultDisplayedFields)).toBeNull();
|
||||
});
|
||||
it('should return null when columns is invalid', () => {
|
||||
const logsState = { columns: 'invalid' };
|
||||
expect(migrateLegacyColumns(logsState, defaultDisplayedFields, 'table')).toBeNull();
|
||||
});
|
||||
|
||||
it('should return null when columns is empty array', () => {
|
||||
const logsState = { columns: [] };
|
||||
expect(migrateLegacyColumns(logsState, defaultDisplayedFields)).toBeNull();
|
||||
});
|
||||
it('should migrate array format columns', () => {
|
||||
const logsState = { columns: ['Time', TABLE_LINE_FIELD_NAME, 'level'] };
|
||||
const result = migrateLegacyColumns(logsState, defaultDisplayedFields, 'table');
|
||||
expect(result).toEqual(['Time', LOG_LINE_BODY_FIELD_NAME, 'level']);
|
||||
});
|
||||
|
||||
it('should return null when columns is invalid', () => {
|
||||
const logsState = { columns: 'invalid' };
|
||||
expect(migrateLegacyColumns(logsState, defaultDisplayedFields)).toBeNull();
|
||||
});
|
||||
it('should migrate object format columns', () => {
|
||||
const logsState = { columns: { 0: 'Time', 1: TABLE_LINE_FIELD_NAME, 2: 'level' } };
|
||||
const result = migrateLegacyColumns(logsState, defaultDisplayedFields, 'table');
|
||||
expect(result).toEqual(['Time', LOG_LINE_BODY_FIELD_NAME, 'level']);
|
||||
});
|
||||
|
||||
it('should migrate array format columns', () => {
|
||||
const logsState = { columns: ['Time', TABLE_LINE_FIELD_NAME, 'level'] };
|
||||
const result = migrateLegacyColumns(logsState, defaultDisplayedFields);
|
||||
expect(result).toEqual(['Time', LOG_LINE_BODY_FIELD_NAME, 'level']);
|
||||
});
|
||||
it('should return only mapped columns without merging with defaults', () => {
|
||||
const logsState = { columns: ['level', 'host'] };
|
||||
const result = migrateLegacyColumns(logsState, defaultDisplayedFields, 'table');
|
||||
// Table visualization returns only the columns, not merged with defaults
|
||||
expect(result).toEqual(['level', 'host']);
|
||||
});
|
||||
|
||||
it('should migrate object format columns', () => {
|
||||
const logsState = { columns: { 0: 'Time', 1: TABLE_LINE_FIELD_NAME, 2: 'level' } };
|
||||
const result = migrateLegacyColumns(logsState, defaultDisplayedFields);
|
||||
expect(result).toEqual(['Time', LOG_LINE_BODY_FIELD_NAME, 'level']);
|
||||
});
|
||||
it('should map Line to body field name', () => {
|
||||
const logsState = { columns: [TABLE_LINE_FIELD_NAME] };
|
||||
const result = migrateLegacyColumns(logsState, defaultDisplayedFields, 'table');
|
||||
expect(result).toEqual([LOG_LINE_BODY_FIELD_NAME]);
|
||||
});
|
||||
|
||||
it('should merge with defaults and avoid duplicates', () => {
|
||||
const logsState = { columns: ['level', 'host'] };
|
||||
const result = migrateLegacyColumns(logsState, defaultDisplayedFields);
|
||||
expect(result).toEqual(['Time', LOG_LINE_BODY_FIELD_NAME, 'level', 'host']);
|
||||
});
|
||||
it('should map timestamp to Time', () => {
|
||||
const logsState = { columns: ['timestamp', 'level'] };
|
||||
const result = migrateLegacyColumns(logsState, defaultDisplayedFields, 'table');
|
||||
expect(result).toEqual(['Time', 'level']);
|
||||
});
|
||||
|
||||
it('should handle columns that are already in defaults', () => {
|
||||
const logsState = { columns: ['Time', 'level'] };
|
||||
const result = migrateLegacyColumns(logsState, defaultDisplayedFields);
|
||||
expect(result).toEqual(['Time', LOG_LINE_BODY_FIELD_NAME, 'level']);
|
||||
});
|
||||
it('should map body to LOG_LINE_BODY_FIELD_NAME', () => {
|
||||
const logsState = { columns: ['body', 'level'] };
|
||||
const result = migrateLegacyColumns(logsState, defaultDisplayedFields, 'table');
|
||||
expect(result).toEqual([LOG_LINE_BODY_FIELD_NAME, 'level']);
|
||||
});
|
||||
|
||||
it('should map Line to body and merge correctly', () => {
|
||||
const logsState = { columns: [TABLE_LINE_FIELD_NAME] };
|
||||
const result = migrateLegacyColumns(logsState, defaultDisplayedFields);
|
||||
// Line maps to LOG_LINE_BODY_FIELD_NAME which is already in defaults
|
||||
expect(result).toEqual(['Time', LOG_LINE_BODY_FIELD_NAME]);
|
||||
});
|
||||
it('should ignore displayedFields and only use columns for table', () => {
|
||||
const logsState = {
|
||||
columns: ['level'],
|
||||
displayedFields: ['existing', 'fields'],
|
||||
};
|
||||
const result = migrateLegacyColumns(logsState, defaultDisplayedFields, 'table');
|
||||
// Should only return mapped columns, ignoring displayedFields
|
||||
expect(result).toEqual(['level']);
|
||||
});
|
||||
|
||||
it('should handle empty defaults', () => {
|
||||
const logsState = { columns: ['Time', TABLE_LINE_FIELD_NAME] };
|
||||
const result = migrateLegacyColumns(logsState, []);
|
||||
expect(result).toEqual(['Time', LOG_LINE_BODY_FIELD_NAME]);
|
||||
});
|
||||
|
||||
it('should preserve other logsState properties conceptually', () => {
|
||||
// This test verifies the function only looks at columns
|
||||
const logsState = {
|
||||
columns: ['level'],
|
||||
visualisationType: 'table',
|
||||
displayedFields: ['existing'],
|
||||
};
|
||||
const result = migrateLegacyColumns(logsState, defaultDisplayedFields);
|
||||
expect(result).toEqual(['Time', LOG_LINE_BODY_FIELD_NAME, 'level']);
|
||||
});
|
||||
|
||||
it('should handle real URL format with full logsState structure', () => {
|
||||
// Real format from URL: columns%22:%7B%220%22:%22cluster%22,%221%22:%22Line%22,%222%22:%22Time%22%7D
|
||||
// Full structure: {"columns":{"0":"cluster","1":"Line","2":"Time"},"visualisationType":"table","labelFieldName":"labels","refId":"A"}
|
||||
const logsState = {
|
||||
columns: { '0': 'cluster', '1': 'Line', '2': 'Time' },
|
||||
visualisationType: 'table',
|
||||
labelFieldName: 'labels',
|
||||
refId: 'A',
|
||||
};
|
||||
const result = migrateLegacyColumns(logsState, defaultDisplayedFields);
|
||||
// cluster is new, Line maps to body (already in defaults), Time is already in defaults
|
||||
expect(result).toEqual(['Time', LOG_LINE_BODY_FIELD_NAME, 'cluster']);
|
||||
});
|
||||
|
||||
describe('real URL format from ops.grafana-ops.net', () => {
|
||||
// URL: https://ops.grafana-ops.net/explore?schemaVersion=1&panes=%7B%2259n%22:...
|
||||
// Decoded panelsState.logs:
|
||||
// {
|
||||
// "sortOrder": "Ascending",
|
||||
// "columns": {"0": "cluster", "1": "Line", "2": "Time"},
|
||||
// "visualisationType": "table",
|
||||
// "labelFieldName": "labels",
|
||||
// "refId": "A"
|
||||
// }
|
||||
it('should handle real URL format with full logsState structure', () => {
|
||||
const logsState = {
|
||||
columns: { '0': 'cluster', '1': 'Line', '2': 'Time' },
|
||||
visualisationType: 'table',
|
||||
labelFieldName: 'labels',
|
||||
refId: 'A',
|
||||
};
|
||||
const result = migrateLegacyColumns(logsState, defaultDisplayedFields, 'table');
|
||||
// Returns mapped columns in order (Line -> LOG_LINE_BODY_FIELD_NAME)
|
||||
expect(result).toEqual(['cluster', LOG_LINE_BODY_FIELD_NAME, 'Time']);
|
||||
});
|
||||
|
||||
it('should migrate columns from real Grafana Explore URL', () => {
|
||||
const logsState = {
|
||||
@@ -293,51 +318,62 @@ describe('columnMigration', () => {
|
||||
labelFieldName: 'labels',
|
||||
refId: 'A',
|
||||
};
|
||||
const result = migrateLegacyColumns(logsState, defaultDisplayedFields);
|
||||
const result = migrateLegacyColumns(logsState, defaultDisplayedFields, 'table');
|
||||
expect(result).toContain('cluster');
|
||||
expect(result).toContain(LOG_LINE_BODY_FIELD_NAME);
|
||||
expect(result).toContain('Time');
|
||||
expect(result).not.toContain('Line'); // Line should be mapped
|
||||
});
|
||||
|
||||
it('should map Line to body field name', () => {
|
||||
it('should map legacy field names correctly', () => {
|
||||
const logsState = {
|
||||
columns: { '0': 'timestamp', '1': 'body', '2': 'env', '3': 'namespace' },
|
||||
};
|
||||
const result = migrateLegacyColumns(logsState, defaultDisplayedFields, 'table');
|
||||
expect(result).toEqual(['Time', LOG_LINE_BODY_FIELD_NAME, 'env', 'namespace']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('visualisationType: logs', () => {
|
||||
it('should return null when no columns property exists (required for migration)', () => {
|
||||
const logsState = { displayedFields: ['Time', 'level'] };
|
||||
// logs visualization requires legacy columns to exist for migration to run
|
||||
expect(migrateLegacyColumns(logsState, defaultDisplayedFields, 'logs')).toBeNull();
|
||||
});
|
||||
|
||||
it('should return displayedFields directly when columns exist', () => {
|
||||
const logsState = {
|
||||
columns: { '0': 'old', '1': 'columns' }, // Legacy columns must exist
|
||||
displayedFields: ['Time', 'level', 'host'],
|
||||
};
|
||||
const result = migrateLegacyColumns(logsState, defaultDisplayedFields, 'logs');
|
||||
expect(result).toEqual(['Time', 'level', 'host']);
|
||||
});
|
||||
|
||||
it('should return null when displayedFields is empty', () => {
|
||||
const logsState = {
|
||||
columns: { '0': 'old' },
|
||||
displayedFields: [],
|
||||
};
|
||||
expect(migrateLegacyColumns(logsState, defaultDisplayedFields, 'logs')).toBeNull();
|
||||
});
|
||||
|
||||
it('should return null when displayedFields is not an array', () => {
|
||||
const logsState = {
|
||||
columns: { '0': 'old' },
|
||||
displayedFields: 'not-an-array',
|
||||
};
|
||||
expect(migrateLegacyColumns(logsState, defaultDisplayedFields, 'logs')).toBeNull();
|
||||
});
|
||||
|
||||
it('should ignore columns and use displayedFields for logs visualization', () => {
|
||||
const logsState = {
|
||||
sortOrder: 'Ascending',
|
||||
columns: { '0': 'cluster', '1': 'Line', '2': 'Time' },
|
||||
visualisationType: 'table',
|
||||
labelFieldName: 'labels',
|
||||
refId: 'A',
|
||||
displayedFields: ['service_name', 'component'],
|
||||
};
|
||||
const result = migrateLegacyColumns(logsState, defaultDisplayedFields);
|
||||
// Line should be mapped to LOG_LINE_BODY_FIELD_NAME, not remain as 'Line'
|
||||
expect(result).not.toContain('Line');
|
||||
expect(result).toContain(LOG_LINE_BODY_FIELD_NAME);
|
||||
});
|
||||
|
||||
it('should place defaults first, then additional columns', () => {
|
||||
const logsState = {
|
||||
sortOrder: 'Ascending',
|
||||
columns: { '0': 'cluster', '1': 'Line', '2': 'Time' },
|
||||
visualisationType: 'table',
|
||||
labelFieldName: 'labels',
|
||||
refId: 'A',
|
||||
};
|
||||
const result = migrateLegacyColumns(logsState, defaultDisplayedFields);
|
||||
// Default fields (Time, body) should come first
|
||||
expect(result![0]).toBe('Time');
|
||||
expect(result![1]).toBe(LOG_LINE_BODY_FIELD_NAME);
|
||||
// Then additional fields from columns (cluster)
|
||||
expect(result![2]).toBe('cluster');
|
||||
});
|
||||
|
||||
it('should not duplicate fields that exist in both defaults and columns', () => {
|
||||
const logsState = {
|
||||
columns: { '0': 'Time', '1': 'Line', '2': 'cluster' },
|
||||
visualisationType: 'table',
|
||||
};
|
||||
const result = migrateLegacyColumns(logsState, defaultDisplayedFields);
|
||||
// Should not have duplicate Time or body entries
|
||||
expect(result!.filter((f) => f === 'Time').length).toBe(1);
|
||||
expect(result!.filter((f) => f === LOG_LINE_BODY_FIELD_NAME).length).toBe(1);
|
||||
const result = migrateLegacyColumns(logsState, defaultDisplayedFields, 'logs');
|
||||
// Should return displayedFields, ignoring columns
|
||||
expect(result).toEqual(['service_name', 'component']);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user