datasource_specs.ts 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  1. import {describe, beforeEach, it, expect, angularMocks} from 'test/lib/common';
  2. import moment from 'moment';
  3. import helpers from 'test/specs/helpers';
  4. import {PrometheusDatasource} from '../datasource';
  5. describe('PrometheusDatasource', function() {
  6. var ctx = new helpers.ServiceTestContext();
  7. var instanceSettings = {url: 'proxied', directUrl: 'direct', user: 'test', password: 'mupp' };
  8. beforeEach(angularMocks.module('grafana.core'));
  9. beforeEach(angularMocks.module('grafana.services'));
  10. beforeEach(ctx.providePhase(['timeSrv']));
  11. beforeEach(angularMocks.inject(function($q, $rootScope, $httpBackend, $injector) {
  12. ctx.$q = $q;
  13. ctx.$httpBackend = $httpBackend;
  14. ctx.$rootScope = $rootScope;
  15. ctx.ds = $injector.instantiate(PrometheusDatasource, {instanceSettings: instanceSettings});
  16. $httpBackend.when('GET', /\.html$/).respond('');
  17. }));
  18. describe('When querying prometheus with one target using query editor target spec', function() {
  19. var results;
  20. var urlExpected = 'proxied/api/v1/query_range?query=' +
  21. encodeURIComponent('test{job="testjob"}') +
  22. '&start=1443438675&end=1443460275&step=60';
  23. var query = {
  24. range: { from: moment(1443438674760), to: moment(1443460274760) },
  25. targets: [{ expr: 'test{job="testjob"}', format: 'time_series' }],
  26. interval: '60s'
  27. };
  28. var response = {
  29. status: "success",
  30. data: {
  31. resultType: "matrix",
  32. result: [{
  33. metric: {"__name__": "test", job: "testjob"},
  34. values: [[1443454528, "3846"]]
  35. }]
  36. }
  37. };
  38. beforeEach(function() {
  39. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  40. ctx.ds.query(query).then(function(data) { results = data; });
  41. ctx.$httpBackend.flush();
  42. });
  43. it('should generate the correct query', function() {
  44. ctx.$httpBackend.verifyNoOutstandingExpectation();
  45. });
  46. it('should return series list', function() {
  47. expect(results.data.length).to.be(1);
  48. expect(results.data[0].target).to.be('test{job="testjob"}');
  49. });
  50. });
  51. describe('When querying prometheus with one target which return multiple series', function() {
  52. var results;
  53. var start = 1443438675;
  54. var end = 1443460275;
  55. var step = 60;
  56. var urlExpected = 'proxied/api/v1/query_range?query=' +
  57. encodeURIComponent('test{job="testjob"}') +
  58. '&start=' + start + '&end=' + end + '&step=' + step;
  59. var query = {
  60. range: { from: moment(1443438674760), to: moment(1443460274760) },
  61. targets: [{ expr: 'test{job="testjob"}', format: 'time_series' }],
  62. interval: '60s'
  63. };
  64. var response = {
  65. status: "success",
  66. data: {
  67. resultType: "matrix",
  68. result: [
  69. {
  70. metric: {"__name__": "test", job: "testjob", series: 'series 1'},
  71. values: [
  72. [start + step * 1, "3846"],
  73. [start + step * 3, "3847"],
  74. [end - step * 1, "3848"],
  75. ]
  76. },
  77. {
  78. metric: {"__name__": "test", job: "testjob", series: 'series 2'},
  79. values: [
  80. [start + step * 2, "4846"]
  81. ]
  82. },
  83. ]
  84. }
  85. };
  86. beforeEach(function() {
  87. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  88. ctx.ds.query(query).then(function(data) { results = data; });
  89. ctx.$httpBackend.flush();
  90. });
  91. it('should be same length', function() {
  92. expect(results.data.length).to.be(2);
  93. expect(results.data[0].datapoints.length).to.be((end - start) / step + 1);
  94. expect(results.data[1].datapoints.length).to.be((end - start) / step + 1);
  95. });
  96. it('should fill null until first datapoint in response', function() {
  97. expect(results.data[0].datapoints[0][1]).to.be(start * 1000);
  98. expect(results.data[0].datapoints[0][0]).to.be(null);
  99. expect(results.data[0].datapoints[1][1]).to.be((start + step * 1) * 1000);
  100. expect(results.data[0].datapoints[1][0]).to.be(3846);
  101. });
  102. it('should fill null after last datapoint in response', function() {
  103. var length = (end - start) / step + 1;
  104. expect(results.data[0].datapoints[length-2][1]).to.be((end - step * 1) * 1000);
  105. expect(results.data[0].datapoints[length-2][0]).to.be(3848);
  106. expect(results.data[0].datapoints[length-1][1]).to.be(end * 1000);
  107. expect(results.data[0].datapoints[length-1][0]).to.be(null);
  108. });
  109. it('should fill null at gap between series', function() {
  110. expect(results.data[0].datapoints[2][1]).to.be((start + step * 2) * 1000);
  111. expect(results.data[0].datapoints[2][0]).to.be(null);
  112. expect(results.data[1].datapoints[1][1]).to.be((start + step * 1) * 1000);
  113. expect(results.data[1].datapoints[1][0]).to.be(null);
  114. expect(results.data[1].datapoints[3][1]).to.be((start + step * 3) * 1000);
  115. expect(results.data[1].datapoints[3][0]).to.be(null);
  116. });
  117. });
  118. describe('When querying prometheus with one target and instant = true', function () {
  119. var results;
  120. var urlExpected = 'proxied/api/v1/query?query=' +
  121. encodeURIComponent('test{job="testjob"}') +
  122. '&time=1443460275';
  123. var query = {
  124. range: { from: moment(1443438674760), to: moment(1443460274760) },
  125. targets: [{ expr: 'test{job="testjob"}', format: 'time_series', instant: true }],
  126. interval: '60s'
  127. };
  128. var response = {
  129. status: "success",
  130. data: {
  131. resultType: "vector",
  132. result: [{
  133. metric: { "__name__": "test", job: "testjob" },
  134. value: [1443454528, "3846"]
  135. }]
  136. }
  137. };
  138. beforeEach(function () {
  139. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  140. ctx.ds.query(query).then(function (data) { results = data; });
  141. ctx.$httpBackend.flush();
  142. });
  143. it('should generate the correct query', function () {
  144. ctx.$httpBackend.verifyNoOutstandingExpectation();
  145. });
  146. it('should return series list', function () {
  147. expect(results.data.length).to.be(1);
  148. expect(results.data[0].target).to.be('test{job="testjob"}');
  149. });
  150. });
  151. describe('When performing annotationQuery', function () {
  152. var results;
  153. var urlExpected = 'proxied/api/v1/query_range?query=' +
  154. encodeURIComponent('ALERTS{alertstate="firing"}') +
  155. '&start=1443438675&end=1443460275&step=60s';
  156. var options = {
  157. annotation: {
  158. expr: 'ALERTS{alertstate="firing"}',
  159. tagKeys: 'job',
  160. titleFormat: '{{alertname}}',
  161. textFormat: '{{instance}}'
  162. },
  163. range: {
  164. from: moment(1443438674760),
  165. to: moment(1443460274760)
  166. }
  167. };
  168. var response = {
  169. status: "success",
  170. data: {
  171. resultType: "matrix",
  172. result: [{
  173. metric: {"__name__": "ALERTS", alertname: "InstanceDown", alertstate: "firing", instance: "testinstance", job: "testjob"},
  174. values: [[1443454528, "1"]]
  175. }]
  176. }
  177. };
  178. beforeEach(function() {
  179. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  180. ctx.ds.annotationQuery(options).then(function(data) { results = data; });
  181. ctx.$httpBackend.flush();
  182. });
  183. it('should return annotation list', function() {
  184. ctx.$rootScope.$apply();
  185. expect(results.length).to.be(1);
  186. expect(results[0].tags).to.contain('testjob');
  187. expect(results[0].title).to.be('InstanceDown');
  188. expect(results[0].text).to.be('testinstance');
  189. expect(results[0].time).to.be(1443454528 * 1000);
  190. });
  191. });
  192. describe('When resultFormat is table', function() {
  193. var response = {
  194. status: "success",
  195. data: {
  196. resultType: "matrix",
  197. result: [
  198. {
  199. metric: {"__name__": "test", job: "testjob"},
  200. values: [[1443454528, "3846"]]
  201. },
  202. {
  203. metric: {"__name__": "test", instance: "localhost:8080", job: "otherjob"},
  204. values: [[1443454529, "3847"]]
  205. },
  206. ]
  207. }
  208. };
  209. it('should return table model', function() {
  210. var table = ctx.ds.transformMetricDataToTable(response.data.result);
  211. expect(table.type).to.be('table');
  212. expect(table.rows).to.eql(
  213. [
  214. [ 1443454528000, 'test', '', 'testjob', 3846],
  215. [ 1443454529000, 'test', 'localhost:8080', "otherjob", 3847],
  216. ]);
  217. expect(table.columns).to.eql(
  218. [ { text: 'Time', type: 'time' },
  219. { text: '__name__' },
  220. { text: 'instance' },
  221. { text: 'job' },
  222. { text: 'Value' }
  223. ]
  224. );
  225. });
  226. });
  227. describe('When resultFormat is table and instant = true', function() {
  228. var results;
  229. var urlExpected = 'proxied/api/v1/query?query=' +
  230. encodeURIComponent('test{job="testjob"}') +
  231. '&time=1443460275';
  232. var query = {
  233. range: { from: moment(1443438674760), to: moment(1443460274760) },
  234. targets: [{ expr: 'test{job="testjob"}', format: 'time_series', instant: true }],
  235. interval: '60s'
  236. };
  237. var response = {
  238. status: "success",
  239. data: {
  240. resultType: "vector",
  241. result: [{
  242. metric: { "__name__": "test", job: "testjob" },
  243. value: [1443454528, "3846"]
  244. }]
  245. }
  246. };
  247. beforeEach(function () {
  248. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  249. ctx.ds.query(query).then(function (data) { results = data; });
  250. ctx.$httpBackend.flush();
  251. });
  252. it('should return table model', function() {
  253. var table = ctx.ds.transformMetricDataToTable(response.data.result);
  254. expect(table.type).to.be('table');
  255. expect(table.rows).to.eql(
  256. [
  257. [ 1443454528000, 'test', 'testjob', 3846]
  258. ]);
  259. expect(table.columns).to.eql(
  260. [ { text: 'Time', type: 'time' },
  261. { text: '__name__' },
  262. { text: 'job' },
  263. { text: 'Value' }
  264. ]
  265. );
  266. });
  267. });
  268. describe('The "step" query parameter', function() {
  269. var response = {
  270. status: "success",
  271. data: {
  272. resultType: "matrix",
  273. result: []
  274. }
  275. };
  276. it('should be min interval when greater than auto interval', function() {
  277. var query = {
  278. // 6 hour range
  279. range: { from: moment(1443438674760), to: moment(1443460274760) },
  280. targets: [{
  281. expr: 'test',
  282. interval: '10s'
  283. }],
  284. interval: '5s'
  285. };
  286. var urlExpected = 'proxied/api/v1/query_range?query=test' +
  287. '&start=1443438675&end=1443460275&step=10';
  288. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  289. ctx.ds.query(query);
  290. ctx.$httpBackend.verifyNoOutstandingExpectation();
  291. });
  292. it('should be auto interval when greater than min interval', function() {
  293. var query = {
  294. // 6 hour range
  295. range: { from: moment(1443438674760), to: moment(1443460274760) },
  296. targets: [{
  297. expr: 'test',
  298. interval: '5s'
  299. }],
  300. interval: '10s'
  301. };
  302. var urlExpected = 'proxied/api/v1/query_range?query=test' +
  303. '&start=1443438675&end=1443460275&step=10';
  304. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  305. ctx.ds.query(query);
  306. ctx.$httpBackend.verifyNoOutstandingExpectation();
  307. });
  308. it('should result in querying fewer than 11000 data points', function() {
  309. var query = {
  310. // 6 hour range
  311. range: { from: moment(1443438674760), to: moment(1443460274760) },
  312. targets: [{ expr: 'test' }],
  313. interval: '1s'
  314. };
  315. var urlExpected = 'proxied/api/v1/query_range?query=test' +
  316. '&start=1443438675&end=1443460275&step=2';
  317. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  318. ctx.ds.query(query);
  319. ctx.$httpBackend.verifyNoOutstandingExpectation();
  320. });
  321. it('should not apply min interval when interval * intervalFactor greater', function() {
  322. var query = {
  323. // 6 hour range
  324. range: { from: moment(1443438674760), to: moment(1443460274760) },
  325. targets: [{
  326. expr: 'test',
  327. interval: '10s',
  328. intervalFactor: 10
  329. }],
  330. interval: '5s'
  331. };
  332. var urlExpected = 'proxied/api/v1/query_range?query=test' +
  333. '&start=1443438675&end=1443460275&step=50';
  334. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  335. ctx.ds.query(query);
  336. ctx.$httpBackend.verifyNoOutstandingExpectation();
  337. });
  338. it('should apply min interval when interval * intervalFactor smaller', function() {
  339. var query = {
  340. // 6 hour range
  341. range: { from: moment(1443438674760), to: moment(1443460274760) },
  342. targets: [{
  343. expr: 'test',
  344. interval: '15s',
  345. intervalFactor: 2
  346. }],
  347. interval: '5s'
  348. };
  349. var urlExpected = 'proxied/api/v1/query_range?query=test' +
  350. '&start=1443438675&end=1443460275&step=15';
  351. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  352. ctx.ds.query(query);
  353. ctx.$httpBackend.verifyNoOutstandingExpectation();
  354. });
  355. it('should apply intervalFactor to auto interval when greater', function() {
  356. var query = {
  357. // 6 hour range
  358. range: { from: moment(1443438674760), to: moment(1443460274760) },
  359. targets: [{
  360. expr: 'test',
  361. interval: '5s',
  362. intervalFactor: 10
  363. }],
  364. interval: '10s'
  365. };
  366. var urlExpected = 'proxied/api/v1/query_range?query=test' +
  367. '&start=1443438675&end=1443460275&step=100';
  368. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  369. ctx.ds.query(query);
  370. ctx.$httpBackend.verifyNoOutstandingExpectation();
  371. });
  372. it('should not not be affected by the 11000 data points limit when large enough', function() {
  373. var query = {
  374. // 1 week range
  375. range: { from: moment(1443438674760), to: moment(1444043474760) },
  376. targets: [{
  377. expr: 'test',
  378. intervalFactor: 10
  379. }],
  380. interval: '10s'
  381. };
  382. var urlExpected = 'proxied/api/v1/query_range?query=test' +
  383. '&start=1443438675&end=1444043475&step=100';
  384. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  385. ctx.ds.query(query);
  386. ctx.$httpBackend.verifyNoOutstandingExpectation();
  387. });
  388. it('should be determined by the 11000 data points limit when too small', function() {
  389. var query = {
  390. // 1 week range
  391. range: { from: moment(1443438674760), to: moment(1444043474760) },
  392. targets: [{
  393. expr: 'test',
  394. intervalFactor: 10
  395. }],
  396. interval: '5s'
  397. };
  398. var urlExpected = 'proxied/api/v1/query_range?query=test' +
  399. '&start=1443438675&end=1444043475&step=60';
  400. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  401. ctx.ds.query(query);
  402. ctx.$httpBackend.verifyNoOutstandingExpectation();
  403. });
  404. });
  405. describe('The __interval and __interval_ms template variables', function() {
  406. var response = {
  407. status: "success",
  408. data: {
  409. resultType: "matrix",
  410. result: []
  411. }
  412. };
  413. it('should be unchanged when auto interval is greater than min interval', function() {
  414. var query = {
  415. // 6 hour range
  416. range: { from: moment(1443438674760), to: moment(1443460274760) },
  417. targets: [{
  418. expr: 'rate(test[$__interval])',
  419. interval: '5s'
  420. }],
  421. interval: '10s',
  422. scopedVars: {
  423. "__interval": {text: "10s", value: "10s"},
  424. "__interval_ms": {text: 10 * 1000, value: 10 * 1000},
  425. }
  426. };
  427. var urlExpected = 'proxied/api/v1/query_range?query=' +
  428. encodeURIComponent('rate(test[10s])') +
  429. '&start=1443438675&end=1443460275&step=10';
  430. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  431. ctx.ds.query(query);
  432. ctx.$httpBackend.verifyNoOutstandingExpectation();
  433. expect(query.scopedVars.__interval.text).to.be("10s");
  434. expect(query.scopedVars.__interval.value).to.be("10s");
  435. expect(query.scopedVars.__interval_ms.text).to.be(10 * 1000);
  436. expect(query.scopedVars.__interval_ms.value).to.be(10 * 1000);
  437. });
  438. it('should be min interval when it is greater than auto interval', function() {
  439. var query = {
  440. // 6 hour range
  441. range: { from: moment(1443438674760), to: moment(1443460274760) },
  442. targets: [{
  443. expr: 'rate(test[$__interval])',
  444. interval: '10s'
  445. }],
  446. interval: '5s',
  447. scopedVars: {
  448. "__interval": {text: "5s", value: "5s"},
  449. "__interval_ms": {text: 5 * 1000, value: 5 * 1000},
  450. }
  451. };
  452. var urlExpected = 'proxied/api/v1/query_range?query=' +
  453. encodeURIComponent('rate(test[10s])') +
  454. '&start=1443438675&end=1443460275&step=10';
  455. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  456. ctx.ds.query(query);
  457. ctx.$httpBackend.verifyNoOutstandingExpectation();
  458. expect(query.scopedVars.__interval.text).to.be("5s");
  459. expect(query.scopedVars.__interval.value).to.be("5s");
  460. expect(query.scopedVars.__interval_ms.text).to.be(5 * 1000);
  461. expect(query.scopedVars.__interval_ms.value).to.be(5 * 1000);
  462. });
  463. it('should account for intervalFactor', function() {
  464. var query = {
  465. // 6 hour range
  466. range: { from: moment(1443438674760), to: moment(1443460274760) },
  467. targets: [{
  468. expr: 'rate(test[$__interval])',
  469. interval: '5s',
  470. intervalFactor: 10
  471. }],
  472. interval: '10s',
  473. scopedVars: {
  474. "__interval": {text: "10s", value: "10s"},
  475. "__interval_ms": {text: 10 * 1000, value: 10 * 1000},
  476. }
  477. };
  478. var urlExpected = 'proxied/api/v1/query_range?query=' +
  479. encodeURIComponent('rate(test[100s])') +
  480. '&start=1443438675&end=1443460275&step=100';
  481. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  482. ctx.ds.query(query);
  483. ctx.$httpBackend.verifyNoOutstandingExpectation();
  484. expect(query.scopedVars.__interval.text).to.be("10s");
  485. expect(query.scopedVars.__interval.value).to.be("10s");
  486. expect(query.scopedVars.__interval_ms.text).to.be(10 * 1000);
  487. expect(query.scopedVars.__interval_ms.value).to.be(10 * 1000);
  488. });
  489. it('should be interval * intervalFactor when greater than min interval', function() {
  490. var query = {
  491. // 6 hour range
  492. range: { from: moment(1443438674760), to: moment(1443460274760) },
  493. targets: [{
  494. expr: 'rate(test[$__interval])',
  495. interval: '10s',
  496. intervalFactor: 10
  497. }],
  498. interval: '5s',
  499. scopedVars: {
  500. "__interval": {text: "5s", value: "5s"},
  501. "__interval_ms": {text: 5 * 1000, value: 5 * 1000},
  502. }
  503. };
  504. var urlExpected = 'proxied/api/v1/query_range?query=' +
  505. encodeURIComponent('rate(test[50s])') +
  506. '&start=1443438675&end=1443460275&step=50';
  507. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  508. ctx.ds.query(query);
  509. ctx.$httpBackend.verifyNoOutstandingExpectation();
  510. expect(query.scopedVars.__interval.text).to.be("5s");
  511. expect(query.scopedVars.__interval.value).to.be("5s");
  512. expect(query.scopedVars.__interval_ms.text).to.be(5 * 1000);
  513. expect(query.scopedVars.__interval_ms.value).to.be(5 * 1000);
  514. });
  515. it('should be min interval when greater than interval * intervalFactor', function() {
  516. var query = {
  517. // 6 hour range
  518. range: { from: moment(1443438674760), to: moment(1443460274760) },
  519. targets: [{
  520. expr: 'rate(test[$__interval])',
  521. interval: '15s',
  522. intervalFactor: 2
  523. }],
  524. interval: '5s',
  525. scopedVars: {
  526. "__interval": {text: "5s", value: "5s"},
  527. "__interval_ms": {text: 5 * 1000, value: 5 * 1000},
  528. }
  529. };
  530. var urlExpected = 'proxied/api/v1/query_range?query=' +
  531. encodeURIComponent('rate(test[15s])') +
  532. '&start=1443438675&end=1443460275&step=15';
  533. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  534. ctx.ds.query(query);
  535. ctx.$httpBackend.verifyNoOutstandingExpectation();
  536. expect(query.scopedVars.__interval.text).to.be("5s");
  537. expect(query.scopedVars.__interval.value).to.be("5s");
  538. expect(query.scopedVars.__interval_ms.text).to.be(5 * 1000);
  539. expect(query.scopedVars.__interval_ms.value).to.be(5 * 1000);
  540. });
  541. it('should be determined by the 11000 data points limit, accounting for intervalFactor', function() {
  542. var query = {
  543. // 1 week range
  544. range: { from: moment(1443438674760), to: moment(1444043474760) },
  545. targets: [{
  546. expr: 'rate(test[$__interval])',
  547. intervalFactor: 10
  548. }],
  549. interval: '5s',
  550. scopedVars: {
  551. "__interval": {text: "5s", value: "5s"},
  552. "__interval_ms": {text: 5 * 1000, value: 5 * 1000},
  553. }
  554. };
  555. var urlExpected = 'proxied/api/v1/query_range?query=' +
  556. encodeURIComponent('rate(test[60s])') +
  557. '&start=1443438675&end=1444043475&step=60';
  558. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  559. ctx.ds.query(query);
  560. ctx.$httpBackend.verifyNoOutstandingExpectation();
  561. expect(query.scopedVars.__interval.text).to.be("5s");
  562. expect(query.scopedVars.__interval.value).to.be("5s");
  563. expect(query.scopedVars.__interval_ms.text).to.be(5 * 1000);
  564. expect(query.scopedVars.__interval_ms.value).to.be(5 * 1000);
  565. });
  566. });
  567. });