grafana/public/app/core/utils/richHistory.test.ts
Gábor Farkas cc271b0a42
Explore: rich history: add more tests (#40769)
* explore: rich history: add unit test

* explore: rich-history: added info comment

* improved comment

* better test names
2021-10-25 15:23:47 +02:00

338 lines
11 KiB
TypeScript

import {
addToRichHistory,
getRichHistory,
updateStarredInRichHistory,
updateCommentInRichHistory,
mapNumbertoTimeInSlider,
createDateStringFromTs,
createQueryHeading,
deleteAllFromRichHistory,
deleteQueryInRichHistory,
filterAndSortQueries,
SortOrder,
MAX_HISTORY_ITEMS,
} from './richHistory';
import store from 'app/core/store';
import { dateTime, DataQuery } from '@grafana/data';
import { RichHistoryQuery } from '../../types';
const mock: any = {
storedHistory: [
{
comment: '',
datasourceId: 'datasource historyId',
datasourceName: 'datasource history name',
queries: [
{ expr: 'query1', maxLines: null, refId: '1' },
{ expr: 'query2', refId: '2' },
],
sessionName: '',
starred: true,
ts: 1,
},
],
testComment: '',
testDatasourceId: 'datasourceId',
testDatasourceName: 'datasourceName',
testQueries: [
{ expr: 'query3', refId: 'B' },
{ expr: 'query4', refId: 'C' },
],
testSessionName: '',
testStarred: false,
};
const key = 'grafana.explore.richHistory';
describe('richHistory', () => {
beforeEach(() => {
jest.useFakeTimers('modern');
jest.setSystemTime(new Date(1970, 0, 1));
});
afterEach(() => {
jest.useRealTimers();
});
describe('addToRichHistory', () => {
beforeEach(() => {
deleteAllFromRichHistory();
expect(store.exists(key)).toBeFalsy();
});
const expectedResult = [
{
comment: mock.testComment,
datasourceId: mock.testDatasourceId,
datasourceName: mock.testDatasourceName,
queries: mock.testQueries,
sessionName: mock.testSessionName,
starred: mock.testStarred,
ts: 2,
},
mock.storedHistory[0],
];
it('should append query to query history', () => {
Date.now = jest.fn(() => 2);
const { richHistory: newHistory } = addToRichHistory(
mock.storedHistory,
mock.testDatasourceId,
mock.testDatasourceName,
mock.testQueries,
mock.testStarred,
mock.testComment,
mock.testSessionName,
true,
true
);
expect(newHistory).toEqual(expectedResult);
});
it('should save query history to localStorage', () => {
Date.now = jest.fn(() => 2);
addToRichHistory(
mock.storedHistory,
mock.testDatasourceId,
mock.testDatasourceName,
mock.testQueries,
mock.testStarred,
mock.testComment,
mock.testSessionName,
true,
true
);
expect(store.exists(key)).toBeTruthy();
expect(store.getObject(key)).toMatchObject(expectedResult);
});
it('should not append duplicated query to query history', () => {
Date.now = jest.fn(() => 2);
const { richHistory: newHistory } = addToRichHistory(
mock.storedHistory,
mock.storedHistory[0].datasourceId,
mock.storedHistory[0].datasourceName,
[{ expr: 'query1', maxLines: null, refId: 'A' } as DataQuery, { expr: 'query2', refId: 'B' } as DataQuery],
mock.testStarred,
mock.testComment,
mock.testSessionName,
true,
true
);
expect(newHistory).toEqual([mock.storedHistory[0]]);
});
it('should not save duplicated query to localStorage', () => {
Date.now = jest.fn(() => 2);
addToRichHistory(
mock.storedHistory,
mock.storedHistory[0].datasourceId,
mock.storedHistory[0].datasourceName,
[{ expr: 'query1', maxLines: null, refId: 'A' } as DataQuery, { expr: 'query2', refId: 'B' } as DataQuery],
mock.testStarred,
mock.testComment,
mock.testSessionName,
true,
true
);
expect(store.exists(key)).toBeFalsy();
});
it('should not save more than MAX_HISTORY_ITEMS', () => {
Date.now = jest.fn(() => 2);
const extraItems = 100;
// the history has more than MAX
let history = [];
// history = [ { starred: true, comment: "0" }, { starred: false, comment: "1" }, ... ]
for (let i = 0; i < MAX_HISTORY_ITEMS + extraItems; i++) {
history.push({
starred: i % 2 === 0,
comment: i.toString(),
queries: [],
ts: new Date(2019, 11, 31).getTime(),
});
}
const starredItemsInHistory = (MAX_HISTORY_ITEMS + extraItems) / 2;
const notStarredItemsInHistory = (MAX_HISTORY_ITEMS + extraItems) / 2;
expect(history.filter((h) => h.starred)).toHaveLength(starredItemsInHistory);
expect(history.filter((h) => !h.starred)).toHaveLength(notStarredItemsInHistory);
const { richHistory: newHistory } = addToRichHistory(
(history as any) as RichHistoryQuery[],
mock.storedHistory[0].datasourceId,
mock.storedHistory[0].datasourceName,
[{ expr: 'query1', maxLines: null, refId: 'A' } as DataQuery, { expr: 'query2', refId: 'B' } as DataQuery],
true,
mock.testComment,
mock.testSessionName,
true,
true
);
// one not starred replaced with a newly added starred item
const removedNotStarredItems = extraItems + 1; // + 1 to make space for the new item
expect(newHistory.filter((h) => h.starred)).toHaveLength(starredItemsInHistory + 1); // starred item added
expect(newHistory.filter((h) => !h.starred)).toHaveLength(starredItemsInHistory - removedNotStarredItems);
});
});
describe('updateStarredInRichHistory', () => {
it('should update starred in query in history', () => {
const updatedStarred = updateStarredInRichHistory(mock.storedHistory, 1);
expect(updatedStarred[0].starred).toEqual(false);
});
it('should update starred in localStorage', () => {
updateStarredInRichHistory(mock.storedHistory, 1);
expect(store.exists(key)).toBeTruthy();
expect(store.getObject(key)[0].starred).toEqual(false);
});
});
describe('updateCommentInRichHistory', () => {
it('should update comment in query in history', () => {
const updatedComment = updateCommentInRichHistory(mock.storedHistory, 1, 'new comment');
expect(updatedComment[0].comment).toEqual('new comment');
});
it('should update comment in localStorage', () => {
updateCommentInRichHistory(mock.storedHistory, 1, 'new comment');
expect(store.exists(key)).toBeTruthy();
expect(store.getObject(key)[0].comment).toEqual('new comment');
});
});
describe('deleteQueryInRichHistory', () => {
it('should delete query in query in history', () => {
const deletedHistory = deleteQueryInRichHistory(mock.storedHistory, 1);
expect(deletedHistory).toEqual([]);
});
it('should delete query in localStorage', () => {
deleteQueryInRichHistory(mock.storedHistory, 1);
expect(store.exists(key)).toBeTruthy();
expect(store.getObject(key)).toEqual([]);
});
});
describe('mapNumbertoTimeInSlider', () => {
it('should correctly map number to value', () => {
const value = mapNumbertoTimeInSlider(25);
expect(value).toEqual('25 days ago');
});
});
describe('createDateStringFromTs', () => {
it('should correctly create string value from timestamp', () => {
const value = createDateStringFromTs(1583932327000);
expect(value).toEqual('March 11');
});
});
describe('filterQueries', () => {
it('should filter out queries based on data source filter', () => {
const filteredQueries = filterAndSortQueries(
mock.storedHistory,
SortOrder.Ascending,
['not provided data source'],
''
);
expect(filteredQueries).toHaveLength(0);
});
it('should keep queries based on data source filter', () => {
const filteredQueries = filterAndSortQueries(
mock.storedHistory,
SortOrder.Ascending,
['datasource history name'],
''
);
expect(filteredQueries).toHaveLength(1);
});
it('should filter out all queries based on search filter', () => {
const filteredQueries = filterAndSortQueries(
mock.storedHistory,
SortOrder.Ascending,
[],
'i do not exist in query'
);
expect(filteredQueries).toHaveLength(0);
});
it('should include queries based on search filter', () => {
const filteredQueries = filterAndSortQueries(mock.storedHistory, SortOrder.Ascending, [], 'query1');
expect(filteredQueries).toHaveLength(1);
});
});
describe('createQueryHeading', () => {
it('should correctly create heading for queries when sort order is ascending ', () => {
// Have to offset the timezone of a 1 microsecond epoch, and then reverse the changes
mock.storedHistory[0].ts = 1 + -1 * dateTime().utcOffset() * 60 * 1000;
const heading = createQueryHeading(mock.storedHistory[0], SortOrder.Ascending);
expect(heading).toEqual('January 1');
});
it('should correctly create heading for queries when sort order is datasourceAZ ', () => {
const heading = createQueryHeading(mock.storedHistory[0], SortOrder.DatasourceAZ);
expect(heading).toEqual(mock.storedHistory[0].datasourceName);
});
});
describe('getRichHistory', () => {
afterEach(() => {
deleteAllFromRichHistory();
expect(store.exists(key)).toBeFalsy();
});
describe('should load from localStorage data in old formats', () => {
it('should load when queries are strings', () => {
const oldHistoryItem = { ...mock.storedHistory[0], queries: ['test query 1', 'test query 2', 'test query 3'] };
store.setObject(key, [oldHistoryItem]);
const expectedHistoryItem = {
...mock.storedHistory[0],
queries: [
{
expr: 'test query 1',
refId: 'A',
},
{
expr: 'test query 2',
refId: 'B',
},
{
expr: 'test query 3',
refId: 'C',
},
],
};
const result = getRichHistory();
expect(result).toStrictEqual([expectedHistoryItem]);
});
it('should load when queries are json-encoded strings', () => {
const oldHistoryItem = {
...mock.storedHistory[0],
queries: ['{"refId":"A","key":"key1","metrics":[]}', '{"refId":"B","key":"key2","metrics":[]}'],
};
store.setObject(key, [oldHistoryItem]);
const expectedHistoryItem = {
...mock.storedHistory[0],
queries: [
{
refId: 'A',
key: 'key1',
metrics: [],
},
{
refId: 'B',
key: 'key2',
metrics: [],
},
],
};
const result = getRichHistory();
expect(result).toStrictEqual([expectedHistoryItem]);
});
});
});
});