variable_srv_init.test.ts 8.1 KB

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