variable_srv_init.test.ts 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. import '../all';
  2. import _ from 'lodash';
  3. import { VariableSrv } from '../variable_srv';
  4. import { DashboardModel } from '../../dashboard/dashboard_model';
  5. import $q from 'q';
  6. describe('VariableSrv init', function(this: any) {
  7. const templateSrv = {
  8. init: vars => {
  9. this.variables = vars;
  10. },
  11. variableInitialized: () => {},
  12. updateIndex: () => {},
  13. replace: str =>
  14. str.replace(this.regex, match => {
  15. return match;
  16. }),
  17. };
  18. const timeSrv = {
  19. timeRange: () => {
  20. return { from: '2018-01-29', to: '2019-01-29' };
  21. },
  22. };
  23. const $injector = {} as any;
  24. const $rootscope = {
  25. $on: () => {},
  26. };
  27. let ctx = {} as any;
  28. function describeInitScenario(desc, fn) {
  29. describe(desc, () => {
  30. const scenario: any = {
  31. urlParams: {},
  32. setup: setupFn => {
  33. scenario.setupFn = setupFn;
  34. },
  35. };
  36. beforeEach(async () => {
  37. scenario.setupFn();
  38. ctx = {
  39. datasource: {
  40. metricFindQuery: jest.fn(() => Promise.resolve(scenario.queryResult)),
  41. },
  42. datasourceSrv: {
  43. get: () => Promise.resolve(ctx.datasource),
  44. getMetricSources: () => scenario.metricSources,
  45. },
  46. templateSrv,
  47. };
  48. // @ts-ignore
  49. ctx.variableSrv = new VariableSrv($rootscope, $q, {}, $injector, templateSrv, timeSrv);
  50. $injector.instantiate = (variable, model) => {
  51. return getVarMockConstructor(variable, model, ctx);
  52. };
  53. ctx.variableSrv.datasource = ctx.datasource;
  54. ctx.variableSrv.datasourceSrv = ctx.datasourceSrv;
  55. ctx.variableSrv.$location.search = () => scenario.urlParams;
  56. ctx.variableSrv.dashboard = new DashboardModel({
  57. templating: { list: scenario.variables },
  58. });
  59. await ctx.variableSrv.init(ctx.variableSrv.dashboard);
  60. scenario.variables = ctx.variableSrv.variables;
  61. });
  62. fn(scenario);
  63. });
  64. }
  65. ['query', 'interval', 'custom', 'datasource'].forEach(type => {
  66. describeInitScenario('when setting ' + type + ' variable via url', scenario => {
  67. scenario.setup(() => {
  68. scenario.variables = [
  69. {
  70. name: 'apps',
  71. type: type,
  72. current: { text: 'Test', value: 'test' },
  73. options: [{ text: 'Test', value: 'test' }],
  74. },
  75. ];
  76. scenario.urlParams['var-apps'] = 'new';
  77. scenario.metricSources = [];
  78. });
  79. it('should update current value', () => {
  80. expect(scenario.variables[0].current.value).toBe('new');
  81. expect(scenario.variables[0].current.text).toBe('new');
  82. });
  83. });
  84. });
  85. describe('given dependent variables', () => {
  86. const variableList = [
  87. {
  88. name: 'app',
  89. type: 'query',
  90. query: '',
  91. current: { text: 'app1', value: 'app1' },
  92. options: [{ text: 'app1', value: 'app1' }],
  93. },
  94. {
  95. name: 'server',
  96. type: 'query',
  97. refresh: 1,
  98. query: '$app.*',
  99. current: { text: 'server1', value: 'server1' },
  100. options: [{ text: 'server1', value: 'server1' }],
  101. },
  102. ];
  103. describeInitScenario('when setting parent const from url', scenario => {
  104. scenario.setup(() => {
  105. scenario.variables = _.cloneDeep(variableList);
  106. scenario.urlParams['var-app'] = 'google';
  107. scenario.queryResult = [{ text: 'google-server1' }, { text: 'google-server2' }];
  108. });
  109. it('should update child variable', () => {
  110. expect(scenario.variables[1].options.length).toBe(2);
  111. expect(scenario.variables[1].current.text).toBe('google-server1');
  112. });
  113. it('should only update it once', () => {
  114. expect(ctx.variableSrv.datasource.metricFindQuery).toHaveBeenCalledTimes(1);
  115. });
  116. });
  117. });
  118. describeInitScenario('when datasource variable is initialized', scenario => {
  119. scenario.setup(() => {
  120. scenario.variables = [
  121. {
  122. type: 'datasource',
  123. query: 'graphite',
  124. name: 'test',
  125. current: { value: 'backend4_pee', text: 'backend4_pee' },
  126. regex: '/pee$/',
  127. },
  128. ];
  129. scenario.metricSources = [
  130. { name: 'backend1', meta: { id: 'influx' } },
  131. { name: 'backend2_pee', meta: { id: 'graphite' } },
  132. { name: 'backend3', meta: { id: 'graphite' } },
  133. { name: 'backend4_pee', meta: { id: 'graphite' } },
  134. ];
  135. });
  136. it('should update current value', () => {
  137. const variable = ctx.variableSrv.variables[0];
  138. expect(variable.options.length).toBe(2);
  139. });
  140. });
  141. describeInitScenario('when template variable is present in url multiple times', scenario => {
  142. scenario.setup(() => {
  143. scenario.variables = [
  144. {
  145. name: 'apps',
  146. type: 'query',
  147. multi: true,
  148. current: { text: 'Val1', value: 'val1' },
  149. options: [
  150. { text: 'Val1', value: 'val1' },
  151. { text: 'Val2', value: 'val2' },
  152. { text: 'Val3', value: 'val3', selected: true },
  153. ],
  154. },
  155. ];
  156. scenario.urlParams['var-apps'] = ['val2', 'val1'];
  157. });
  158. it('should update current value', () => {
  159. const variable = ctx.variableSrv.variables[0];
  160. expect(variable.current.value.length).toBe(2);
  161. expect(variable.current.value[0]).toBe('val2');
  162. expect(variable.current.value[1]).toBe('val1');
  163. expect(variable.current.text).toBe('Val2 + Val1');
  164. expect(variable.options[0].selected).toBe(true);
  165. expect(variable.options[1].selected).toBe(true);
  166. });
  167. it('should set options that are not in value to selected false', () => {
  168. const variable = ctx.variableSrv.variables[0];
  169. expect(variable.options[2].selected).toBe(false);
  170. });
  171. });
  172. describeInitScenario(
  173. 'when template variable is present in url multiple times and variables have no text',
  174. scenario => {
  175. scenario.setup(() => {
  176. scenario.variables = [
  177. {
  178. name: 'apps',
  179. type: 'query',
  180. multi: true,
  181. },
  182. ];
  183. scenario.urlParams['var-apps'] = ['val1', 'val2'];
  184. });
  185. it('should display concatenated values in text', () => {
  186. const variable = ctx.variableSrv.variables[0];
  187. expect(variable.current.value.length).toBe(2);
  188. expect(variable.current.value[0]).toBe('val1');
  189. expect(variable.current.value[1]).toBe('val2');
  190. expect(variable.current.text).toBe('val1 + val2');
  191. });
  192. }
  193. );
  194. describeInitScenario('when template variable is present in url multiple times using key/values', scenario => {
  195. scenario.setup(() => {
  196. scenario.variables = [
  197. {
  198. name: 'apps',
  199. type: 'query',
  200. multi: true,
  201. current: { text: 'Val1', value: 'val1' },
  202. options: [
  203. { text: 'Val1', value: 'val1' },
  204. { text: 'Val2', value: 'val2' },
  205. { text: 'Val3', value: 'val3', selected: true },
  206. ],
  207. },
  208. ];
  209. scenario.urlParams['var-apps'] = ['val2', 'val1'];
  210. });
  211. it('should update current value', () => {
  212. const variable = ctx.variableSrv.variables[0];
  213. expect(variable.current.value.length).toBe(2);
  214. expect(variable.current.value[0]).toBe('val2');
  215. expect(variable.current.value[1]).toBe('val1');
  216. expect(variable.current.text).toBe('Val2 + Val1');
  217. expect(variable.options[0].selected).toBe(true);
  218. expect(variable.options[1].selected).toBe(true);
  219. });
  220. it('should set options that are not in value to selected false', () => {
  221. const variable = ctx.variableSrv.variables[0];
  222. expect(variable.options[2].selected).toBe(false);
  223. });
  224. });
  225. });
  226. function getVarMockConstructor(variable, model, ctx) {
  227. switch (model.model.type) {
  228. case 'datasource':
  229. return new variable(model.model, ctx.datasourceSrv, ctx.variableSrv, ctx.templateSrv);
  230. case 'query':
  231. return new variable(model.model, ctx.datasourceSrv, ctx.templateSrv, ctx.variableSrv);
  232. case 'interval':
  233. return new variable(model.model, {}, ctx.templateSrv, ctx.variableSrv);
  234. case 'custom':
  235. return new variable(model.model, ctx.variableSrv);
  236. default:
  237. return new variable(model.model);
  238. }
  239. }