datasource.test.ts 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. import StackdriverDataSource from '../datasource';
  2. import { metricDescriptors } from './testData';
  3. import { TemplateSrv } from 'app/features/templating/template_srv';
  4. import { CustomVariable } from 'app/features/templating/all';
  5. import { toUtc } from '@grafana/ui/src/utils/moment_wrapper';
  6. import { DataSourceInstanceSettings } from '@grafana/ui';
  7. import { StackdriverOptions } from '../types';
  8. import { BackendSrv } from 'app/core/services/backend_srv';
  9. import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
  10. describe('StackdriverDataSource', () => {
  11. const instanceSettings = ({
  12. jsonData: {
  13. defaultProject: 'testproject',
  14. },
  15. } as unknown) as DataSourceInstanceSettings<StackdriverOptions>;
  16. const templateSrv = new TemplateSrv();
  17. const timeSrv = {} as TimeSrv;
  18. describe('when performing testDataSource', () => {
  19. describe('and call to stackdriver api succeeds', () => {
  20. let ds;
  21. let result;
  22. beforeEach(async () => {
  23. const backendSrv = ({
  24. async datasourceRequest() {
  25. return Promise.resolve({ status: 200 });
  26. },
  27. } as unknown) as BackendSrv;
  28. ds = new StackdriverDataSource(instanceSettings, backendSrv, templateSrv, timeSrv);
  29. result = await ds.testDatasource();
  30. });
  31. it('should return successfully', () => {
  32. expect(result.status).toBe('success');
  33. });
  34. });
  35. describe('and a list of metricDescriptors are returned', () => {
  36. let ds;
  37. let result;
  38. beforeEach(async () => {
  39. const backendSrv = ({
  40. datasourceRequest: async () => Promise.resolve({ status: 200, data: metricDescriptors }),
  41. } as unknown) as BackendSrv;
  42. ds = new StackdriverDataSource(instanceSettings, backendSrv, templateSrv, timeSrv);
  43. result = await ds.testDatasource();
  44. });
  45. it('should return status success', () => {
  46. expect(result.status).toBe('success');
  47. });
  48. });
  49. describe('and call to stackdriver api fails with 400 error', () => {
  50. let ds;
  51. let result;
  52. beforeEach(async () => {
  53. const backendSrv = ({
  54. datasourceRequest: async () =>
  55. Promise.reject({
  56. statusText: 'Bad Request',
  57. data: {
  58. error: { code: 400, message: 'Field interval.endTime had an invalid value' },
  59. },
  60. }),
  61. } as unknown) as BackendSrv;
  62. ds = new StackdriverDataSource(instanceSettings, backendSrv, templateSrv, timeSrv);
  63. result = await ds.testDatasource();
  64. });
  65. it('should return error status and a detailed error message', () => {
  66. expect(result.status).toEqual('error');
  67. expect(result.message).toBe('Stackdriver: Bad Request: 400. Field interval.endTime had an invalid value');
  68. });
  69. });
  70. });
  71. describe('When performing query', () => {
  72. const options = {
  73. range: {
  74. from: toUtc('2017-08-22T20:00:00Z'),
  75. to: toUtc('2017-08-22T23:59:00Z'),
  76. },
  77. rangeRaw: {
  78. from: 'now-4h',
  79. to: 'now',
  80. },
  81. targets: [
  82. {
  83. refId: 'A',
  84. },
  85. ],
  86. };
  87. describe('and no time series data is returned', () => {
  88. let ds;
  89. const response = {
  90. results: {
  91. A: {
  92. refId: 'A',
  93. meta: {
  94. rawQuery: 'arawquerystring',
  95. },
  96. series: null,
  97. tables: null,
  98. },
  99. },
  100. };
  101. beforeEach(() => {
  102. const backendSrv = ({
  103. datasourceRequest: async () => Promise.resolve({ status: 200, data: response }),
  104. } as unknown) as BackendSrv;
  105. ds = new StackdriverDataSource(instanceSettings, backendSrv, templateSrv, timeSrv);
  106. });
  107. it('should return a list of datapoints', () => {
  108. return ds.query(options).then(results => {
  109. expect(results.data.length).toBe(0);
  110. });
  111. });
  112. });
  113. });
  114. describe('when performing getMetricTypes', () => {
  115. describe('and call to stackdriver api succeeds', () => {});
  116. let ds;
  117. let result;
  118. beforeEach(async () => {
  119. const backendSrv = ({
  120. async datasourceRequest() {
  121. return Promise.resolve({
  122. data: {
  123. metricDescriptors: [
  124. {
  125. displayName: 'test metric name 1',
  126. type: 'compute.googleapis.com/instance/cpu/test-metric-type-1',
  127. description: 'A description',
  128. },
  129. {
  130. type: 'logging.googleapis.com/user/logbased-metric-with-no-display-name',
  131. },
  132. ],
  133. },
  134. });
  135. },
  136. } as unknown) as BackendSrv;
  137. ds = new StackdriverDataSource(instanceSettings, backendSrv, templateSrv, timeSrv);
  138. result = await ds.getMetricTypes();
  139. });
  140. it('should return successfully', () => {
  141. expect(result.length).toBe(2);
  142. expect(result[0].service).toBe('compute.googleapis.com');
  143. expect(result[0].serviceShortName).toBe('compute');
  144. expect(result[0].type).toBe('compute.googleapis.com/instance/cpu/test-metric-type-1');
  145. expect(result[0].displayName).toBe('test metric name 1');
  146. expect(result[0].description).toBe('A description');
  147. expect(result[1].type).toBe('logging.googleapis.com/user/logbased-metric-with-no-display-name');
  148. expect(result[1].displayName).toBe('logging.googleapis.com/user/logbased-metric-with-no-display-name');
  149. });
  150. });
  151. const noopBackendSrv = ({} as unknown) as BackendSrv;
  152. describe('when interpolating a template variable for the filter', () => {
  153. let interpolated;
  154. describe('and is single value variable', () => {
  155. beforeEach(() => {
  156. const filterTemplateSrv = initTemplateSrv('filtervalue1');
  157. const ds = new StackdriverDataSource(instanceSettings, noopBackendSrv, filterTemplateSrv, timeSrv);
  158. interpolated = ds.interpolateFilters(['resource.label.zone', '=~', '${test}'], {});
  159. });
  160. it('should replace the variable with the value', () => {
  161. expect(interpolated.length).toBe(3);
  162. expect(interpolated[2]).toBe('filtervalue1');
  163. });
  164. });
  165. describe('and is multi value variable', () => {
  166. beforeEach(() => {
  167. const filterTemplateSrv = initTemplateSrv(['filtervalue1', 'filtervalue2'], true);
  168. const ds = new StackdriverDataSource(instanceSettings, noopBackendSrv, filterTemplateSrv, timeSrv);
  169. interpolated = ds.interpolateFilters(['resource.label.zone', '=~', '[[test]]'], {});
  170. });
  171. it('should replace the variable with a regex expression', () => {
  172. expect(interpolated[2]).toBe('(filtervalue1|filtervalue2)');
  173. });
  174. });
  175. });
  176. describe('when interpolating a template variable for group bys', () => {
  177. let interpolated;
  178. describe('and is single value variable', () => {
  179. beforeEach(() => {
  180. const groupByTemplateSrv = initTemplateSrv('groupby1');
  181. const ds = new StackdriverDataSource(instanceSettings, noopBackendSrv, groupByTemplateSrv, timeSrv);
  182. interpolated = ds.interpolateGroupBys(['[[test]]'], {});
  183. });
  184. it('should replace the variable with the value', () => {
  185. expect(interpolated.length).toBe(1);
  186. expect(interpolated[0]).toBe('groupby1');
  187. });
  188. });
  189. describe('and is multi value variable', () => {
  190. beforeEach(() => {
  191. const groupByTemplateSrv = initTemplateSrv(['groupby1', 'groupby2'], true);
  192. const ds = new StackdriverDataSource(instanceSettings, noopBackendSrv, groupByTemplateSrv, timeSrv);
  193. interpolated = ds.interpolateGroupBys(['[[test]]'], {});
  194. });
  195. it('should replace the variable with an array of group bys', () => {
  196. expect(interpolated.length).toBe(2);
  197. expect(interpolated[0]).toBe('groupby1');
  198. expect(interpolated[1]).toBe('groupby2');
  199. });
  200. });
  201. });
  202. describe('unit parsing', () => {
  203. let ds, res;
  204. beforeEach(() => {
  205. ds = new StackdriverDataSource(instanceSettings, noopBackendSrv, templateSrv, timeSrv);
  206. });
  207. describe('when theres only one target', () => {
  208. describe('and the stackdriver unit doesnt have a corresponding grafana unit', () => {
  209. beforeEach(() => {
  210. res = ds.resolvePanelUnitFromTargets([{ unit: 'megaseconds' }]);
  211. });
  212. it('should return undefined', () => {
  213. expect(res).toBeUndefined();
  214. });
  215. });
  216. describe('and the stackdriver unit has a corresponding grafana unit', () => {
  217. beforeEach(() => {
  218. res = ds.resolvePanelUnitFromTargets([{ unit: 'bit' }]);
  219. });
  220. it('should return bits', () => {
  221. expect(res).toEqual('bits');
  222. });
  223. });
  224. });
  225. describe('when theres more than one target', () => {
  226. describe('and all target units are the same', () => {
  227. beforeEach(() => {
  228. res = ds.resolvePanelUnitFromTargets([{ unit: 'bit' }, { unit: 'bit' }]);
  229. });
  230. it('should return bits', () => {
  231. expect(res).toEqual('bits');
  232. });
  233. });
  234. describe('and all target units are the same but doesnt have grafana mappings', () => {
  235. beforeEach(() => {
  236. res = ds.resolvePanelUnitFromTargets([{ unit: 'megaseconds' }, { unit: 'megaseconds' }]);
  237. });
  238. it('should return the default value of undefined', () => {
  239. expect(res).toBeUndefined();
  240. });
  241. });
  242. describe('and all target units are not the same', () => {
  243. beforeEach(() => {
  244. res = ds.resolvePanelUnitFromTargets([{ unit: 'bit' }, { unit: 'min' }]);
  245. });
  246. it('should return the default value of undefined', () => {
  247. expect(res).toBeUndefined();
  248. });
  249. });
  250. });
  251. });
  252. });
  253. function initTemplateSrv(values: any, multi = false) {
  254. const templateSrv = new TemplateSrv();
  255. templateSrv.init([
  256. new CustomVariable(
  257. {
  258. name: 'test',
  259. current: {
  260. value: values,
  261. },
  262. multi: multi,
  263. },
  264. {}
  265. ),
  266. ]);
  267. return templateSrv;
  268. }