updateQueries.test.ts 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. import {
  2. DataQuery,
  3. DataSourceApi,
  4. DataSourceWithQueryExportSupport,
  5. DataSourceWithQueryImportSupport,
  6. } from '@grafana/data';
  7. import { ExpressionDatasourceRef } from '@grafana/runtime/src/utils/DataSourceWithBackend';
  8. import { updateQueries } from './updateQueries';
  9. const oldUidDS = {
  10. uid: 'old-uid',
  11. type: 'old-type',
  12. meta: {
  13. id: 'old-type',
  14. },
  15. } as DataSourceApi;
  16. const mixedDS = {
  17. uid: 'mixed',
  18. meta: {
  19. id: 'mixed',
  20. mixed: true,
  21. },
  22. } as DataSourceApi;
  23. const newUidDS = {
  24. uid: 'new-uid',
  25. type: 'new-type',
  26. meta: {
  27. id: 'new-type',
  28. },
  29. } as DataSourceApi;
  30. const newUidSameTypeDS = {
  31. uid: 'new-uid-same-type',
  32. type: 'old-type',
  33. meta: {
  34. id: 'old-type',
  35. },
  36. } as DataSourceApi;
  37. describe('updateQueries', () => {
  38. it('Should update all queries except expression query when changing data source with same type', async () => {
  39. const updated = await updateQueries(
  40. newUidSameTypeDS,
  41. 'new-uid-same-type',
  42. [
  43. {
  44. refId: 'A',
  45. datasource: {
  46. uid: 'old-uid',
  47. type: 'old-type',
  48. },
  49. },
  50. {
  51. refId: 'B',
  52. datasource: ExpressionDatasourceRef,
  53. },
  54. ],
  55. oldUidDS
  56. );
  57. expect(updated[0].datasource).toEqual({ type: 'old-type', uid: 'new-uid-same-type' });
  58. expect(updated[1].datasource).toEqual(ExpressionDatasourceRef);
  59. });
  60. it('Should update all to uid string passed in even when different from real current ds uid', async () => {
  61. const updated = await updateQueries(
  62. newUidSameTypeDS,
  63. '${ds}',
  64. [
  65. {
  66. refId: 'A',
  67. datasource: {
  68. uid: 'old-uid',
  69. type: 'old-type',
  70. },
  71. },
  72. ],
  73. oldUidDS
  74. );
  75. expect(updated[0].datasource).toEqual({ type: 'old-type', uid: '${ds}' });
  76. });
  77. it('Should clear queries when changing type', async () => {
  78. const updated = await updateQueries(
  79. newUidDS,
  80. 'new-uid',
  81. [
  82. {
  83. refId: 'A',
  84. datasource: {
  85. uid: 'old-uid',
  86. type: 'old-type',
  87. },
  88. },
  89. {
  90. refId: 'B',
  91. datasource: {
  92. uid: 'old-uid',
  93. type: 'old-type',
  94. },
  95. },
  96. ],
  97. oldUidDS
  98. );
  99. expect(updated.length).toEqual(1);
  100. expect(updated[0].datasource).toEqual({ type: 'new-type', uid: 'new-uid' });
  101. });
  102. it('Should preserve query data source when changing to mixed', async () => {
  103. const updated = await updateQueries(
  104. mixedDS,
  105. 'mixed',
  106. [
  107. {
  108. refId: 'A',
  109. datasource: {
  110. uid: 'old-uid',
  111. type: 'old-type',
  112. },
  113. },
  114. {
  115. refId: 'B',
  116. datasource: {
  117. uid: 'other-uid',
  118. type: 'other-type',
  119. },
  120. },
  121. ],
  122. oldUidDS
  123. );
  124. expect(updated[0].datasource).toEqual({ type: 'old-type', uid: 'old-uid' });
  125. expect(updated[1].datasource).toEqual({ type: 'other-type', uid: 'other-uid' });
  126. });
  127. it('should change nothing mixed updated to mixed', async () => {
  128. const updated = await updateQueries(
  129. mixedDS,
  130. 'mixed',
  131. [
  132. {
  133. refId: 'A',
  134. datasource: {
  135. uid: 'old-uid',
  136. type: 'old-type',
  137. },
  138. },
  139. {
  140. refId: 'B',
  141. datasource: {
  142. uid: 'other-uid',
  143. type: 'other-type',
  144. },
  145. },
  146. ],
  147. mixedDS
  148. );
  149. expect(updated[0].datasource).toEqual({ type: 'old-type', uid: 'old-uid' });
  150. expect(updated[1].datasource).toEqual({ type: 'other-type', uid: 'other-uid' });
  151. });
  152. });
  153. describe('updateQueries with import', () => {
  154. describe('abstract queries support', () => {
  155. it('should migrate abstract queries', async () => {
  156. const exportSpy = jest.fn();
  157. const importSpy = jest.fn();
  158. const newUidDSWithAbstract = {
  159. uid: 'new-uid',
  160. type: 'new-type',
  161. meta: {
  162. id: 'new-type',
  163. },
  164. importFromAbstractQueries: (queries) => {
  165. importSpy(queries);
  166. const importedQueries = queries.map((q) => ({ ...q, imported: true }));
  167. return Promise.resolve(importedQueries);
  168. },
  169. } as DataSourceWithQueryImportSupport<any>;
  170. const oldUidDSWithAbstract = {
  171. uid: 'old-uid',
  172. type: 'old-type',
  173. meta: {
  174. id: 'old-type',
  175. },
  176. exportToAbstractQueries: (queries) => {
  177. exportSpy(queries);
  178. const exportedQueries = queries.map((q) => ({ ...q, exported: true }));
  179. return Promise.resolve(exportedQueries);
  180. },
  181. } as DataSourceWithQueryExportSupport<any>;
  182. const queries = [
  183. {
  184. refId: 'A',
  185. datasource: {
  186. uid: 'old-uid',
  187. type: 'old-type',
  188. },
  189. },
  190. {
  191. refId: 'B',
  192. datasource: {
  193. uid: 'other-uid',
  194. type: 'other-type',
  195. },
  196. },
  197. ];
  198. const updated = await updateQueries(
  199. newUidDSWithAbstract as any,
  200. (newUidDSWithAbstract as any).uid,
  201. queries,
  202. oldUidDSWithAbstract as any
  203. );
  204. expect(exportSpy).toBeCalledWith(queries);
  205. expect(importSpy).toBeCalledWith(queries.map((q) => ({ ...q, exported: true })));
  206. expect(updated).toMatchInlineSnapshot(`
  207. Array [
  208. Object {
  209. "datasource": Object {
  210. "type": "new-type",
  211. "uid": "new-uid",
  212. },
  213. "exported": true,
  214. "imported": true,
  215. "refId": "A",
  216. },
  217. Object {
  218. "datasource": Object {
  219. "type": "new-type",
  220. "uid": "new-uid",
  221. },
  222. "exported": true,
  223. "imported": true,
  224. "refId": "B",
  225. },
  226. ]
  227. `);
  228. });
  229. it('should clear queries when no queries were imported', async () => {
  230. const newUidDSWithAbstract = {
  231. uid: 'new-uid',
  232. type: 'new-type',
  233. meta: {
  234. id: 'new-type',
  235. },
  236. importFromAbstractQueries: () => {
  237. return Promise.resolve([]);
  238. },
  239. } as DataSourceWithQueryImportSupport<any>;
  240. const oldUidDSWithAbstract = {
  241. uid: 'old-uid',
  242. type: 'old-type',
  243. meta: {
  244. id: 'old-type',
  245. },
  246. exportToAbstractQueries: (queries) => {
  247. const exportedQueries = queries.map((q) => ({ ...q, exported: true }));
  248. return Promise.resolve(exportedQueries);
  249. },
  250. } as DataSourceWithQueryExportSupport<any>;
  251. const queries = [
  252. {
  253. refId: 'A',
  254. datasource: {
  255. uid: 'old-uid',
  256. type: 'old-type',
  257. },
  258. },
  259. {
  260. refId: 'B',
  261. datasource: {
  262. uid: 'other-uid',
  263. type: 'other-type',
  264. },
  265. },
  266. ];
  267. const updated = await updateQueries(
  268. newUidDSWithAbstract as any,
  269. (newUidDSWithAbstract as any).uid,
  270. queries,
  271. oldUidDSWithAbstract as any
  272. );
  273. expect(updated.length).toEqual(1);
  274. expect(updated[0].datasource).toEqual({ type: 'new-type', uid: 'new-uid' });
  275. });
  276. });
  277. describe('importQueries support', () => {
  278. it('should import queries when abstract queries are not supported by datasources', async () => {
  279. const importSpy = jest.fn();
  280. const newUidDSWithImport = {
  281. uid: 'new-uid',
  282. type: 'new-type',
  283. meta: {
  284. id: 'new-type',
  285. },
  286. importQueries: (queries, origin) => {
  287. importSpy(queries, origin);
  288. const importedQueries = queries.map((q) => ({ ...q, imported: true }));
  289. return Promise.resolve(importedQueries);
  290. },
  291. } as DataSourceApi<any>;
  292. const oldUidDS = {
  293. uid: 'old-uid',
  294. type: 'old-type',
  295. meta: {
  296. id: 'old-type',
  297. },
  298. } as DataSourceApi;
  299. const queries = [
  300. {
  301. refId: 'A',
  302. datasource: {
  303. uid: 'old-uid',
  304. type: 'old-type',
  305. },
  306. },
  307. {
  308. refId: 'B',
  309. datasource: {
  310. uid: 'other-uid',
  311. type: 'other-type',
  312. },
  313. },
  314. ];
  315. const updated = await updateQueries(newUidDSWithImport, newUidDSWithImport.uid, queries, oldUidDS);
  316. expect(importSpy).toBeCalledWith(queries, { uid: 'old-uid', type: 'old-type', meta: { id: 'old-type' } });
  317. expect(updated).toMatchInlineSnapshot(`
  318. Array [
  319. Object {
  320. "datasource": Object {
  321. "type": "new-type",
  322. "uid": "new-uid",
  323. },
  324. "imported": true,
  325. "refId": "A",
  326. },
  327. Object {
  328. "datasource": Object {
  329. "type": "new-type",
  330. "uid": "new-uid",
  331. },
  332. "imported": true,
  333. "refId": "B",
  334. },
  335. ]
  336. `);
  337. });
  338. it('should clear queries when no queries were imported', async () => {
  339. const newUidDSWithImport = {
  340. uid: 'new-uid',
  341. type: 'new-type',
  342. meta: {
  343. id: 'new-type',
  344. },
  345. importQueries: (queries, origin) => {
  346. return Promise.resolve([] as DataQuery[]);
  347. },
  348. } as DataSourceApi<any>;
  349. const oldUidDS = {
  350. uid: 'old-uid',
  351. type: 'old-type',
  352. meta: {
  353. id: 'old-type',
  354. },
  355. } as DataSourceApi;
  356. const queries = [
  357. {
  358. refId: 'A',
  359. datasource: {
  360. uid: 'old-uid',
  361. type: 'old-type',
  362. },
  363. },
  364. {
  365. refId: 'B',
  366. datasource: {
  367. uid: 'other-uid',
  368. type: 'other-type',
  369. },
  370. },
  371. ];
  372. const updated = await updateQueries(newUidDSWithImport, 'new-uid', queries, oldUidDS);
  373. expect(updated.length).toEqual(1);
  374. expect(updated[0].datasource).toEqual({ type: 'new-type', uid: 'new-uid' });
  375. });
  376. });
  377. });