prepareTimeSeries.test.ts 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. import {
  2. toDataFrame,
  3. ArrayVector,
  4. DataFrame,
  5. FieldType,
  6. toDataFrameDTO,
  7. DataFrameDTO,
  8. DataFrameType,
  9. getFrameDisplayName,
  10. } from '@grafana/data';
  11. import { prepareTimeSeriesTransformer, PrepareTimeSeriesOptions, timeSeriesFormat } from './prepareTimeSeries';
  12. describe('Prepare time series transformer', () => {
  13. it('should transform wide to many', () => {
  14. const source = [
  15. toDataFrame({
  16. name: 'wide',
  17. refId: 'A',
  18. fields: [
  19. { name: 'time', type: FieldType.time, values: [1, 2, 3, 4, 5, 6] },
  20. { name: 'count', type: FieldType.number, values: [10, 20, 30, 40, 50, 60] },
  21. { name: 'more', type: FieldType.number, values: [2, 3, 4, 5, 6, 7] },
  22. ],
  23. }),
  24. ];
  25. const config: PrepareTimeSeriesOptions = {
  26. format: timeSeriesFormat.TimeSeriesMany,
  27. };
  28. expect(prepareTimeSeriesTransformer.transformer(config)(source)).toEqual([
  29. toEquableDataFrame({
  30. name: 'wide',
  31. refId: 'A',
  32. fields: [
  33. { name: 'time', type: FieldType.time, values: [1, 2, 3, 4, 5, 6] },
  34. { name: 'count', type: FieldType.number, values: [10, 20, 30, 40, 50, 60] },
  35. ],
  36. meta: {
  37. type: DataFrameType.TimeSeriesMany,
  38. },
  39. length: 6,
  40. }),
  41. toEquableDataFrame({
  42. name: 'wide',
  43. refId: 'A',
  44. fields: [
  45. { name: 'time', type: FieldType.time, values: [1, 2, 3, 4, 5, 6] },
  46. { name: 'more', type: FieldType.number, values: [2, 3, 4, 5, 6, 7] },
  47. ],
  48. meta: {
  49. type: DataFrameType.TimeSeriesMany,
  50. },
  51. length: 6,
  52. }),
  53. ]);
  54. });
  55. it('should treat string fields as labels', () => {
  56. const source = [
  57. toDataFrame({
  58. name: 'wide',
  59. refId: 'A',
  60. fields: [
  61. { name: 'time', type: FieldType.time, values: [1, 1, 2, 2] },
  62. { name: 'region', type: FieldType.string, values: ['a', 'b', 'a', 'b'] },
  63. { name: 'count', type: FieldType.number, values: [10, 20, 30, 40] },
  64. { name: 'more', type: FieldType.number, values: [2, 3, 4, 5] },
  65. ],
  66. }),
  67. ];
  68. const config: PrepareTimeSeriesOptions = {
  69. format: timeSeriesFormat.TimeSeriesMany,
  70. };
  71. const frames = prepareTimeSeriesTransformer.transformer(config)(source);
  72. expect(frames.length).toEqual(4);
  73. expect(
  74. frames.map((f) => ({
  75. name: getFrameDisplayName(f),
  76. labels: f.fields[1].labels,
  77. time: f.fields[0].values.toArray(),
  78. values: f.fields[1].values.toArray(),
  79. }))
  80. ).toMatchInlineSnapshot(`
  81. Array [
  82. Object {
  83. "labels": Object {
  84. "region": "a",
  85. },
  86. "name": "wide",
  87. "time": Array [
  88. 1,
  89. 2,
  90. ],
  91. "values": Array [
  92. 10,
  93. 30,
  94. ],
  95. },
  96. Object {
  97. "labels": Object {
  98. "region": "b",
  99. },
  100. "name": "wide",
  101. "time": Array [
  102. 1,
  103. 2,
  104. ],
  105. "values": Array [
  106. 20,
  107. 40,
  108. ],
  109. },
  110. Object {
  111. "labels": Object {
  112. "region": "a",
  113. },
  114. "name": "wide",
  115. "time": Array [
  116. 1,
  117. 2,
  118. ],
  119. "values": Array [
  120. 2,
  121. 4,
  122. ],
  123. },
  124. Object {
  125. "labels": Object {
  126. "region": "b",
  127. },
  128. "name": "wide",
  129. "time": Array [
  130. 1,
  131. 2,
  132. ],
  133. "values": Array [
  134. 3,
  135. 5,
  136. ],
  137. },
  138. ]
  139. `);
  140. });
  141. it('should transform all wide to many when mixed', () => {
  142. const source = [
  143. toDataFrame({
  144. name: 'wide',
  145. refId: 'A',
  146. fields: [
  147. { name: 'time', type: FieldType.time, values: [0, 1, 2, 3, 4, 5] },
  148. { name: 'count', type: FieldType.number, values: [10, 20, 30, 40, 50, 60] },
  149. { name: 'another', type: FieldType.number, values: [2, 3, 4, 5, 6, 7] },
  150. ],
  151. }),
  152. toDataFrame({
  153. name: 'long',
  154. refId: 'B',
  155. fields: [
  156. { name: 'time', type: FieldType.time, values: [4, 5, 6, 7, 8, 9] },
  157. { name: 'value', type: FieldType.number, values: [2, 3, 4, 5, 6, 7] },
  158. ],
  159. }),
  160. ];
  161. const config: PrepareTimeSeriesOptions = {
  162. format: timeSeriesFormat.TimeSeriesMany,
  163. };
  164. expect(prepareTimeSeriesTransformer.transformer(config)(source)).toEqual([
  165. toEquableDataFrame({
  166. name: 'wide',
  167. refId: 'A',
  168. fields: [
  169. { name: 'time', type: FieldType.time, values: [0, 1, 2, 3, 4, 5] },
  170. { name: 'another', type: FieldType.number, values: [2, 3, 4, 5, 6, 7] },
  171. ],
  172. length: 6,
  173. meta: {
  174. type: DataFrameType.TimeSeriesMany,
  175. },
  176. }),
  177. toEquableDataFrame({
  178. name: 'wide',
  179. refId: 'A',
  180. fields: [
  181. { name: 'time', type: FieldType.time, values: [0, 1, 2, 3, 4, 5] },
  182. { name: 'count', type: FieldType.number, values: [10, 20, 30, 40, 50, 60] },
  183. ],
  184. length: 6,
  185. meta: {
  186. type: DataFrameType.TimeSeriesMany,
  187. },
  188. }),
  189. toEquableDataFrame({
  190. name: 'long',
  191. refId: 'B',
  192. fields: [
  193. { name: 'time', type: FieldType.time, values: [4, 5, 6, 7, 8, 9] },
  194. { name: 'value', type: FieldType.number, values: [2, 3, 4, 5, 6, 7] },
  195. ],
  196. length: 6,
  197. meta: {
  198. type: DataFrameType.TimeSeriesMany,
  199. },
  200. }),
  201. ]);
  202. });
  203. it('should transform none when source only has long frames', () => {
  204. const source = [
  205. toDataFrame({
  206. name: 'long',
  207. refId: 'A',
  208. fields: [
  209. { name: 'time', type: FieldType.time, values: [1, 2, 3, 4, 5, 6] },
  210. { name: 'count', type: FieldType.number, values: [10, 20, 30, 40, 50, 60] },
  211. ],
  212. }),
  213. toDataFrame({
  214. name: 'long',
  215. refId: 'B',
  216. fields: [
  217. { name: 'time', type: FieldType.time, values: [1, 2, 3, 4, 5, 6] },
  218. { name: 'count', type: FieldType.number, values: [10, 20, 30, 40, 50, 60] },
  219. ],
  220. }),
  221. ];
  222. const config: PrepareTimeSeriesOptions = {
  223. format: timeSeriesFormat.TimeSeriesMany,
  224. };
  225. expect(toEquableDataFrames(prepareTimeSeriesTransformer.transformer(config)(source))).toEqual(
  226. toEquableDataFrames(
  227. source.map((frame) => ({
  228. ...frame,
  229. meta: {
  230. type: DataFrameType.TimeSeriesMany,
  231. },
  232. }))
  233. )
  234. );
  235. });
  236. it('should return empty array when no timeseries exist', () => {
  237. const source = [
  238. toDataFrame({
  239. name: 'wide',
  240. refId: 'A',
  241. fields: [
  242. { name: 'text', type: FieldType.string, values: ['a', 'z', 'b', 'x', 'c', 'b'] },
  243. { name: 'text', type: FieldType.string, values: ['a', 'z', 'b', 'x', 'c', 'b'] },
  244. { name: 'text', type: FieldType.string, values: ['a', 'z', 'b', 'x', 'c', 'b'] },
  245. ],
  246. }),
  247. toDataFrame({
  248. name: 'wide',
  249. refId: 'B',
  250. fields: [
  251. { name: 'text', type: FieldType.string, values: ['a', 'z', 'b', 'x', 'c', 'b'] },
  252. { name: 'text', type: FieldType.string, values: ['a', 'z', 'b', 'x', 'c', 'b'] },
  253. { name: 'text', type: FieldType.string, values: ['a', 'z', 'b', 'x', 'c', 'b'] },
  254. ],
  255. }),
  256. ];
  257. const config: PrepareTimeSeriesOptions = {
  258. format: timeSeriesFormat.TimeSeriesMany,
  259. };
  260. expect(prepareTimeSeriesTransformer.transformer(config)(source)).toEqual([]);
  261. });
  262. it('should convert long to many', () => {
  263. const source = [
  264. toDataFrame({
  265. name: 'long',
  266. refId: 'X',
  267. fields: [
  268. { name: 'time', type: FieldType.time, values: [1, 1, 2, 2, 3, 3] },
  269. { name: 'value', type: FieldType.number, values: [10, 20, 30, 40, 50, 60] },
  270. { name: 'region', type: FieldType.string, values: ['a', 'b', 'a', 'b', 'a', 'b'] },
  271. ],
  272. }),
  273. ];
  274. const config: PrepareTimeSeriesOptions = {
  275. format: timeSeriesFormat.TimeSeriesMany,
  276. };
  277. const frames = prepareTimeSeriesTransformer.transformer(config)(source);
  278. expect(frames).toEqual([
  279. toEquableDataFrame({
  280. name: 'long',
  281. refId: 'X',
  282. fields: [
  283. { name: 'time', type: FieldType.time, values: [1, 2, 3] },
  284. { name: 'value', labels: { region: 'a' }, type: FieldType.number, values: [10, 30, 50] },
  285. ],
  286. length: 3,
  287. meta: {
  288. type: DataFrameType.TimeSeriesMany,
  289. },
  290. }),
  291. toEquableDataFrame({
  292. name: 'long',
  293. refId: 'X',
  294. fields: [
  295. { name: 'time', type: FieldType.time, values: [1, 2, 3] },
  296. { name: 'value', labels: { region: 'b' }, type: FieldType.number, values: [20, 40, 60] },
  297. ],
  298. length: 3,
  299. meta: {
  300. type: DataFrameType.TimeSeriesMany,
  301. },
  302. }),
  303. ]);
  304. });
  305. });
  306. function toEquableDataFrame(source: any): DataFrame {
  307. return toDataFrame({
  308. meta: undefined,
  309. ...source,
  310. fields: source.fields.map((field: any) => {
  311. return {
  312. ...field,
  313. values: new ArrayVector(field.values),
  314. config: {},
  315. };
  316. }),
  317. });
  318. }
  319. function toEquableDataFrames(data: DataFrame[]): DataFrameDTO[] {
  320. return data.map((frame) => toDataFrameDTO(frame));
  321. }