ResultProcessor.test.ts 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. jest.mock('@grafana/data/src/utils/moment_wrapper', () => ({
  2. dateTime: (ts: any) => {
  3. return {
  4. valueOf: () => ts,
  5. fromNow: () => 'fromNow() jest mocked',
  6. format: (fmt: string) => 'format() jest mocked',
  7. };
  8. },
  9. toUtc: (ts: any) => {
  10. return {
  11. format: (fmt: string) => 'format() jest mocked',
  12. };
  13. },
  14. }));
  15. import { ResultProcessor } from './ResultProcessor';
  16. import { ExploreItemState, ExploreMode } from 'app/types/explore';
  17. import TableModel from 'app/core/table_model';
  18. import { TimeSeries, LogRowModel, LogsMetaItem, GraphSeriesXY, toDataFrame, FieldType } from '@grafana/data';
  19. const testContext = (options: any = {}) => {
  20. const timeSeries = toDataFrame({
  21. name: 'A-series',
  22. refId: 'A',
  23. fields: [
  24. { name: 'A-series', type: FieldType.number, values: [4, 5, 6] },
  25. { name: 'time', type: FieldType.time, values: [100, 200, 300] },
  26. ],
  27. });
  28. const table = toDataFrame({
  29. name: 'table-res',
  30. refId: 'A',
  31. fields: [
  32. { name: 'value', type: FieldType.number, values: [4, 5, 6] },
  33. { name: 'time', type: FieldType.time, values: [100, 200, 300] },
  34. { name: 'message', type: FieldType.string, values: ['this is a message', 'second message', 'third'] },
  35. ],
  36. });
  37. const defaultOptions = {
  38. mode: ExploreMode.Metrics,
  39. replacePreviousResults: true,
  40. dataFrames: [timeSeries, table],
  41. graphResult: [] as TimeSeries[],
  42. tableResult: new TableModel(),
  43. logsResult: { hasUniqueLabels: false, rows: [] as LogRowModel[] },
  44. };
  45. const combinedOptions = { ...defaultOptions, ...options };
  46. const state = ({
  47. mode: combinedOptions.mode,
  48. graphResult: combinedOptions.graphResult,
  49. tableResult: combinedOptions.tableResult,
  50. logsResult: combinedOptions.logsResult,
  51. queryIntervals: { intervalMs: 10 },
  52. } as any) as ExploreItemState;
  53. const resultProcessor = new ResultProcessor(
  54. state,
  55. combinedOptions.replacePreviousResults,
  56. combinedOptions.dataFrames
  57. );
  58. return {
  59. dataFrames: combinedOptions.dataFrames,
  60. resultProcessor,
  61. };
  62. };
  63. describe('ResultProcessor', () => {
  64. describe('constructed without result', () => {
  65. describe('when calling getGraphResult', () => {
  66. it('then it should return an empty array', () => {
  67. const { resultProcessor } = testContext({ dataFrames: [] });
  68. const theResult = resultProcessor.getGraphResult();
  69. expect(theResult).toEqual([]);
  70. });
  71. });
  72. describe('when calling getTableResult', () => {
  73. it('then it should return an empty TableModel', () => {
  74. const { resultProcessor } = testContext({ dataFrames: [] });
  75. const theResult = resultProcessor.getTableResult();
  76. expect(theResult).toEqual(new TableModel());
  77. });
  78. });
  79. describe('when calling getLogsResult', () => {
  80. it('then it should return null', () => {
  81. const { resultProcessor } = testContext({ dataFrames: [] });
  82. const theResult = resultProcessor.getLogsResult();
  83. expect(theResult).toBeNull();
  84. });
  85. });
  86. });
  87. describe('constructed with a result that is a DataQueryResponse', () => {
  88. describe('when calling getGraphResult', () => {
  89. it('then it should return correct graph result', () => {
  90. const { resultProcessor } = testContext();
  91. const theResult = resultProcessor.getGraphResult();
  92. expect(theResult).toEqual([
  93. {
  94. label: 'A-series',
  95. color: '#7EB26D',
  96. data: [[100, 4], [200, 5], [300, 6]],
  97. info: undefined,
  98. isVisible: true,
  99. yAxis: {
  100. index: 1,
  101. },
  102. },
  103. ]);
  104. });
  105. });
  106. describe('when calling getTableResult', () => {
  107. it('then it should return correct table result', () => {
  108. const { resultProcessor } = testContext();
  109. const theResult = resultProcessor.getTableResult();
  110. expect(theResult).toEqual({
  111. columnMap: {},
  112. columns: [
  113. { text: 'value', type: 'number', filterable: undefined },
  114. { text: 'time', type: 'time', filterable: undefined },
  115. { text: 'message', type: 'string', filterable: undefined },
  116. ],
  117. rows: [[4, 100, 'this is a message'], [5, 200, 'second message'], [6, 300, 'third']],
  118. type: 'table',
  119. });
  120. });
  121. });
  122. describe('when calling getLogsResult', () => {
  123. it('then it should return correct logs result', () => {
  124. const { resultProcessor } = testContext({ mode: ExploreMode.Logs });
  125. const theResult = resultProcessor.getLogsResult();
  126. expect(theResult).toEqual({
  127. hasUniqueLabels: false,
  128. meta: [],
  129. rows: [
  130. {
  131. entry: 'third',
  132. hasAnsi: false,
  133. labels: undefined,
  134. logLevel: 'unknown',
  135. raw: 'third',
  136. searchWords: [] as string[],
  137. timeEpochMs: 300,
  138. timeFromNow: 'fromNow() jest mocked',
  139. timeLocal: 'format() jest mocked',
  140. timeUtc: 'format() jest mocked',
  141. timestamp: 300,
  142. uniqueLabels: {},
  143. },
  144. {
  145. entry: 'second message',
  146. hasAnsi: false,
  147. labels: undefined,
  148. logLevel: 'unknown',
  149. raw: 'second message',
  150. searchWords: [] as string[],
  151. timeEpochMs: 200,
  152. timeFromNow: 'fromNow() jest mocked',
  153. timeLocal: 'format() jest mocked',
  154. timeUtc: 'format() jest mocked',
  155. timestamp: 200,
  156. uniqueLabels: {},
  157. },
  158. {
  159. entry: 'this is a message',
  160. hasAnsi: false,
  161. labels: undefined,
  162. logLevel: 'unknown',
  163. raw: 'this is a message',
  164. searchWords: [] as string[],
  165. timeEpochMs: 100,
  166. timeFromNow: 'fromNow() jest mocked',
  167. timeLocal: 'format() jest mocked',
  168. timeUtc: 'format() jest mocked',
  169. timestamp: 100,
  170. uniqueLabels: {},
  171. },
  172. ],
  173. series: [
  174. {
  175. label: 'A-series',
  176. color: '#7EB26D',
  177. data: [[100, 4], [200, 5], [300, 6]],
  178. info: undefined,
  179. isVisible: true,
  180. yAxis: {
  181. index: 1,
  182. },
  183. },
  184. ],
  185. });
  186. });
  187. });
  188. });
  189. describe('constructed with result that is a DataQueryResponse and merging with previous results', () => {
  190. describe('when calling getLogsResult', () => {
  191. it('then it should return correct logs result', () => {
  192. const { resultProcessor } = testContext({
  193. mode: ExploreMode.Logs,
  194. replacePreviousResults: false,
  195. logsResult: {
  196. hasUniqueLabels: false,
  197. meta: [],
  198. rows: [
  199. {
  200. entry: 'This is a previous message 1',
  201. fresh: true,
  202. hasAnsi: false,
  203. labels: { cluster: 'some-cluster' },
  204. logLevel: 'unknown',
  205. raw: 'This is a previous message 1',
  206. searchWords: [] as string[],
  207. timeEpochMs: 1558038519831,
  208. timeFromNow: 'fromNow() jest mocked',
  209. timeLocal: 'format() jest mocked',
  210. timeUtc: 'format() jest mocked',
  211. timestamp: 1558038519831,
  212. uniqueLabels: {},
  213. },
  214. {
  215. entry: 'This is a previous message 2',
  216. fresh: true,
  217. hasAnsi: false,
  218. labels: { cluster: 'some-cluster' },
  219. logLevel: 'unknown',
  220. raw: 'This is a previous message 2',
  221. searchWords: [] as string[],
  222. timeEpochMs: 1558038518831,
  223. timeFromNow: 'fromNow() jest mocked',
  224. timeLocal: 'format() jest mocked',
  225. timeUtc: 'format() jest mocked',
  226. timestamp: 1558038518831,
  227. uniqueLabels: {},
  228. },
  229. ],
  230. series: [
  231. {
  232. label: 'A-series',
  233. color: '#7EB26D',
  234. data: [[1558038518831, 37.91264531864214], [1558038519831, 38.35179822906545]],
  235. info: undefined,
  236. isVisible: true,
  237. yAxis: {
  238. index: 1,
  239. },
  240. },
  241. ],
  242. },
  243. });
  244. const theResult = resultProcessor.getLogsResult();
  245. const expected = {
  246. hasUniqueLabels: false,
  247. meta: [] as LogsMetaItem[],
  248. rows: [
  249. {
  250. entry: 'This is a previous message 1',
  251. fresh: false,
  252. hasAnsi: false,
  253. labels: { cluster: 'some-cluster' },
  254. logLevel: 'unknown',
  255. raw: 'This is a previous message 1',
  256. searchWords: [] as string[],
  257. timeEpochMs: 1558038519831,
  258. timeFromNow: 'fromNow() jest mocked',
  259. timeLocal: 'format() jest mocked',
  260. timeUtc: 'format() jest mocked',
  261. timestamp: 1558038519831,
  262. uniqueLabels: {},
  263. },
  264. {
  265. entry: 'This is a previous message 2',
  266. fresh: false,
  267. hasAnsi: false,
  268. labels: { cluster: 'some-cluster' },
  269. logLevel: 'unknown',
  270. raw: 'This is a previous message 2',
  271. searchWords: [] as string[],
  272. timeEpochMs: 1558038518831,
  273. timeFromNow: 'fromNow() jest mocked',
  274. timeLocal: 'format() jest mocked',
  275. timeUtc: 'format() jest mocked',
  276. timestamp: 1558038518831,
  277. uniqueLabels: {},
  278. },
  279. {
  280. entry: 'third',
  281. fresh: true,
  282. hasAnsi: false,
  283. labels: undefined,
  284. logLevel: 'unknown',
  285. raw: 'third',
  286. searchWords: [] as string[],
  287. timeEpochMs: 300,
  288. timeFromNow: 'fromNow() jest mocked',
  289. timeLocal: 'format() jest mocked',
  290. timeUtc: 'format() jest mocked',
  291. timestamp: 300,
  292. uniqueLabels: {},
  293. },
  294. {
  295. entry: 'second message',
  296. fresh: true,
  297. hasAnsi: false,
  298. labels: undefined,
  299. logLevel: 'unknown',
  300. raw: 'second message',
  301. searchWords: [] as string[],
  302. timeEpochMs: 200,
  303. timeFromNow: 'fromNow() jest mocked',
  304. timeLocal: 'format() jest mocked',
  305. timeUtc: 'format() jest mocked',
  306. timestamp: 200,
  307. uniqueLabels: {},
  308. },
  309. {
  310. entry: 'this is a message',
  311. fresh: true,
  312. hasAnsi: false,
  313. labels: undefined,
  314. logLevel: 'unknown',
  315. raw: 'this is a message',
  316. searchWords: [] as string[],
  317. timeEpochMs: 100,
  318. timeFromNow: 'fromNow() jest mocked',
  319. timeLocal: 'format() jest mocked',
  320. timeUtc: 'format() jest mocked',
  321. timestamp: 100,
  322. uniqueLabels: {},
  323. },
  324. ],
  325. series: [
  326. {
  327. label: 'A-series',
  328. color: '#7EB26D',
  329. data: [[100, 4], [200, 5], [300, 6]],
  330. info: undefined,
  331. isVisible: true,
  332. yAxis: {
  333. index: 1,
  334. },
  335. } as GraphSeriesXY,
  336. ],
  337. };
  338. expect(theResult).toEqual(expected);
  339. });
  340. });
  341. });
  342. });