variable_srv_init.test.ts 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  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. updateTemplateData: () => {},
  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. ctx.variableSrv = new VariableSrv($rootscope, $q, {}, $injector, templateSrv, timeSrv);
  49. $injector.instantiate = (variable, model) => {
  50. return getVarMockConstructor(variable, model, ctx);
  51. };
  52. ctx.variableSrv.datasource = ctx.datasource;
  53. ctx.variableSrv.datasourceSrv = ctx.datasourceSrv;
  54. ctx.variableSrv.$location.search = () => scenario.urlParams;
  55. ctx.variableSrv.dashboard = new DashboardModel({
  56. templating: { list: scenario.variables },
  57. });
  58. await ctx.variableSrv.init(ctx.variableSrv.dashboard);
  59. scenario.variables = ctx.variableSrv.variables;
  60. });
  61. fn(scenario);
  62. });
  63. }
  64. ['query', 'interval', 'custom', 'datasource'].forEach(type => {
  65. describeInitScenario('when setting ' + type + ' variable via url', scenario => {
  66. scenario.setup(() => {
  67. scenario.variables = [
  68. {
  69. name: 'apps',
  70. type: type,
  71. current: { text: 'Test', value: 'test' },
  72. options: [{ text: 'Test', value: 'test' }],
  73. },
  74. ];
  75. scenario.urlParams['var-apps'] = 'new';
  76. scenario.metricSources = [];
  77. });
  78. it('should update current value', () => {
  79. expect(scenario.variables[0].current.value).toBe('new');
  80. expect(scenario.variables[0].current.text).toBe('new');
  81. });
  82. });
  83. });
  84. describe('given dependent variables', () => {
  85. const variableList = [
  86. {
  87. name: 'app',
  88. type: 'query',
  89. query: '',
  90. current: { text: 'app1', value: 'app1' },
  91. options: [{ text: 'app1', value: 'app1' }],
  92. },
  93. {
  94. name: 'server',
  95. type: 'query',
  96. refresh: 1,
  97. query: '$app.*',
  98. current: { text: 'server1', value: 'server1' },
  99. options: [{ text: 'server1', value: 'server1' }],
  100. },
  101. ];
  102. describeInitScenario('when setting parent const from url', scenario => {
  103. scenario.setup(() => {
  104. scenario.variables = _.cloneDeep(variableList);
  105. scenario.urlParams['var-app'] = 'google';
  106. scenario.queryResult = [{ text: 'google-server1' }, { text: 'google-server2' }];
  107. });
  108. it('should update child variable', () => {
  109. expect(scenario.variables[1].options.length).toBe(2);
  110. expect(scenario.variables[1].current.text).toBe('google-server1');
  111. });
  112. it('should only update it once', () => {
  113. expect(ctx.variableSrv.datasource.metricFindQuery).toHaveBeenCalledTimes(1);
  114. });
  115. });
  116. });
  117. describeInitScenario('when datasource variable is initialized', scenario => {
  118. scenario.setup(() => {
  119. scenario.variables = [
  120. {
  121. type: 'datasource',
  122. query: 'graphite',
  123. name: 'test',
  124. current: { value: 'backend4_pee', text: 'backend4_pee' },
  125. regex: '/pee$/',
  126. },
  127. ];
  128. scenario.metricSources = [
  129. { name: 'backend1', meta: { id: 'influx' } },
  130. { name: 'backend2_pee', meta: { id: 'graphite' } },
  131. { name: 'backend3', meta: { id: 'graphite' } },
  132. { name: 'backend4_pee', meta: { id: 'graphite' } },
  133. ];
  134. });
  135. it('should update current value', () => {
  136. const variable = ctx.variableSrv.variables[0];
  137. expect(variable.options.length).toBe(2);
  138. });
  139. });
  140. describeInitScenario('when template variable is present in url multiple times', scenario => {
  141. scenario.setup(() => {
  142. scenario.variables = [
  143. {
  144. name: 'apps',
  145. type: 'query',
  146. multi: true,
  147. current: { text: 'Val1', value: 'val1' },
  148. options: [
  149. { text: 'Val1', value: 'val1' },
  150. { text: 'Val2', value: 'val2' },
  151. { text: 'Val3', value: 'val3', selected: true },
  152. ],
  153. },
  154. ];
  155. scenario.urlParams['var-apps'] = ['val2', 'val1'];
  156. });
  157. it('should update current value', () => {
  158. const variable = ctx.variableSrv.variables[0];
  159. expect(variable.current.value.length).toBe(2);
  160. expect(variable.current.value[0]).toBe('val2');
  161. expect(variable.current.value[1]).toBe('val1');
  162. expect(variable.current.text).toBe('Val2 + Val1');
  163. expect(variable.options[0].selected).toBe(true);
  164. expect(variable.options[1].selected).toBe(true);
  165. });
  166. it('should set options that are not in value to selected false', () => {
  167. const variable = ctx.variableSrv.variables[0];
  168. expect(variable.options[2].selected).toBe(false);
  169. });
  170. });
  171. describeInitScenario(
  172. 'when template variable is present in url multiple times and variables have no text',
  173. scenario => {
  174. scenario.setup(() => {
  175. scenario.variables = [
  176. {
  177. name: 'apps',
  178. type: 'query',
  179. multi: true,
  180. },
  181. ];
  182. scenario.urlParams['var-apps'] = ['val1', 'val2'];
  183. });
  184. it('should display concatenated values in text', () => {
  185. const variable = ctx.variableSrv.variables[0];
  186. expect(variable.current.value.length).toBe(2);
  187. expect(variable.current.value[0]).toBe('val1');
  188. expect(variable.current.value[1]).toBe('val2');
  189. expect(variable.current.text).toBe('val1 + val2');
  190. });
  191. }
  192. );
  193. describeInitScenario('when template variable is present in url multiple times using key/values', scenario => {
  194. scenario.setup(() => {
  195. scenario.variables = [
  196. {
  197. name: 'apps',
  198. type: 'query',
  199. multi: true,
  200. current: { text: 'Val1', value: 'val1' },
  201. options: [
  202. { text: 'Val1', value: 'val1' },
  203. { text: 'Val2', value: 'val2' },
  204. { text: 'Val3', value: 'val3', selected: true },
  205. ],
  206. },
  207. ];
  208. scenario.urlParams['var-apps'] = ['val2', 'val1'];
  209. });
  210. it('should update current value', () => {
  211. const variable = ctx.variableSrv.variables[0];
  212. expect(variable.current.value.length).toBe(2);
  213. expect(variable.current.value[0]).toBe('val2');
  214. expect(variable.current.value[1]).toBe('val1');
  215. expect(variable.current.text).toBe('Val2 + Val1');
  216. expect(variable.options[0].selected).toBe(true);
  217. expect(variable.options[1].selected).toBe(true);
  218. });
  219. it('should set options that are not in value to selected false', () => {
  220. const variable = ctx.variableSrv.variables[0];
  221. expect(variable.options[2].selected).toBe(false);
  222. });
  223. });
  224. });
  225. function getVarMockConstructor(variable, model, ctx) {
  226. switch (model.model.type) {
  227. case 'datasource':
  228. return new variable(model.model, ctx.datasourceSrv, ctx.variableSrv, ctx.templateSrv);
  229. case 'query':
  230. return new variable(model.model, ctx.datasourceSrv, ctx.templateSrv, ctx.variableSrv);
  231. case 'interval':
  232. return new variable(model.model, {}, ctx.templateSrv, ctx.variableSrv);
  233. case 'custom':
  234. return new variable(model.model, ctx.variableSrv);
  235. default:
  236. return new variable(model.model);
  237. }
  238. }