datasource_specs.ts 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  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. beforeEach(function() {
  277. ctx.$httpBackend.flush();
  278. });
  279. it('should be min interval when greater than auto interval', function() {
  280. var query = {
  281. // 6 hour range
  282. range: { from: moment(1443438674760), to: moment(1443460274760) },
  283. targets: [{
  284. expr: 'test',
  285. interval: '10s'
  286. }],
  287. interval: '5s'
  288. };
  289. var urlExpected = 'proxied/api/v1/query_range?query=test' +
  290. '&start=1443438675&end=1443460275&step=10';
  291. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  292. ctx.ds.query(query);
  293. ctx.$httpBackend.verifyNoOutstandingExpectation();
  294. });
  295. it('should be auto interval when greater than min interval', function() {
  296. var query = {
  297. // 6 hour range
  298. range: { from: moment(1443438674760), to: moment(1443460274760) },
  299. targets: [{
  300. expr: 'test',
  301. interval: '5s'
  302. }],
  303. interval: '10s'
  304. };
  305. var urlExpected = 'proxied/api/v1/query_range?query=test' +
  306. '&start=1443438675&end=1443460275&step=10';
  307. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  308. ctx.ds.query(query);
  309. ctx.$httpBackend.verifyNoOutstandingExpectation();
  310. });
  311. it('should result in querying fewer than 11000 data points', function() {
  312. var query = {
  313. // 6 hour range
  314. range: { from: moment(1443438674760), to: moment(1443460274760) },
  315. targets: [{ expr: 'test' }],
  316. interval: '1s'
  317. };
  318. var urlExpected = 'proxied/api/v1/query_range?query=test' +
  319. '&start=1443438675&end=1443460275&step=2';
  320. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  321. ctx.ds.query(query);
  322. ctx.$httpBackend.verifyNoOutstandingExpectation();
  323. });
  324. it('should not apply min interval when interval * intervalFactor greater', function() {
  325. var query = {
  326. // 6 hour range
  327. range: { from: moment(1443438674760), to: moment(1443460274760) },
  328. targets: [{
  329. expr: 'test',
  330. interval: '10s',
  331. intervalFactor: 10
  332. }],
  333. interval: '5s'
  334. };
  335. var urlExpected = 'proxied/api/v1/query_range?query=test' +
  336. '&start=1443438675&end=1443460275&step=50';
  337. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  338. ctx.ds.query(query);
  339. ctx.$httpBackend.verifyNoOutstandingExpectation();
  340. });
  341. it('should apply min interval when interval * intervalFactor smaller', function() {
  342. var query = {
  343. // 6 hour range
  344. range: { from: moment(1443438674760), to: moment(1443460274760) },
  345. targets: [{
  346. expr: 'test',
  347. interval: '15s',
  348. intervalFactor: 2
  349. }],
  350. interval: '5s'
  351. };
  352. var urlExpected = 'proxied/api/v1/query_range?query=test' +
  353. '&start=1443438675&end=1443460275&step=15';
  354. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  355. ctx.ds.query(query);
  356. ctx.$httpBackend.verifyNoOutstandingExpectation();
  357. });
  358. it('should apply intervalFactor to auto interval when greater', function() {
  359. var query = {
  360. // 6 hour range
  361. range: { from: moment(1443438674760), to: moment(1443460274760) },
  362. targets: [{
  363. expr: 'test',
  364. interval: '5s',
  365. intervalFactor: 10
  366. }],
  367. interval: '10s'
  368. };
  369. var urlExpected = 'proxied/api/v1/query_range?query=test' +
  370. '&start=1443438675&end=1443460275&step=100';
  371. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  372. ctx.ds.query(query);
  373. ctx.$httpBackend.verifyNoOutstandingExpectation();
  374. });
  375. it('should not not be affected by the 11000 data points limit when large enough', function() {
  376. var query = {
  377. // 1 week range
  378. range: { from: moment(1443438674760), to: moment(1444043474760) },
  379. targets: [{
  380. expr: 'test',
  381. intervalFactor: 10
  382. }],
  383. interval: '10s'
  384. };
  385. var urlExpected = 'proxied/api/v1/query_range?query=test' +
  386. '&start=1443438675&end=1444043475&step=100';
  387. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  388. ctx.ds.query(query);
  389. ctx.$httpBackend.verifyNoOutstandingExpectation();
  390. });
  391. it('should be determined by the 11000 data points limit when too small', function() {
  392. var query = {
  393. // 1 week range
  394. range: { from: moment(1443438674760), to: moment(1444043474760) },
  395. targets: [{
  396. expr: 'test',
  397. intervalFactor: 10
  398. }],
  399. interval: '5s'
  400. };
  401. var urlExpected = 'proxied/api/v1/query_range?query=test' +
  402. '&start=1443438675&end=1444043475&step=60';
  403. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  404. ctx.ds.query(query);
  405. ctx.$httpBackend.verifyNoOutstandingExpectation();
  406. });
  407. });
  408. describe('The __interval and __interval_ms template variables', function() {
  409. var response = {
  410. status: "success",
  411. data: {
  412. resultType: "matrix",
  413. result: []
  414. }
  415. };
  416. beforeEach(function() {
  417. ctx.$httpBackend.flush();
  418. });
  419. it('should be unchanged when auto interval is greater than min interval', function() {
  420. var query = {
  421. // 6 hour range
  422. range: { from: moment(1443438674760), to: moment(1443460274760) },
  423. targets: [{
  424. expr: 'rate(test[$__interval])',
  425. interval: '5s'
  426. }],
  427. interval: '10s',
  428. scopedVars: {
  429. "__interval": {text: "10s", value: "10s"},
  430. "__interval_ms": {text: 10 * 1000, value: 10 * 1000},
  431. }
  432. };
  433. var urlExpected = 'proxied/api/v1/query_range?query=' +
  434. encodeURIComponent('rate(test[10s])') +
  435. '&start=1443438675&end=1443460275&step=10';
  436. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  437. ctx.ds.query(query);
  438. ctx.$httpBackend.verifyNoOutstandingExpectation();
  439. expect(query.scopedVars.__interval.text).to.be("10s");
  440. expect(query.scopedVars.__interval.value).to.be("10s");
  441. expect(query.scopedVars.__interval_ms.text).to.be(10 * 1000);
  442. expect(query.scopedVars.__interval_ms.value).to.be(10 * 1000);
  443. });
  444. it('should be min interval when it is greater than auto interval', function() {
  445. var query = {
  446. // 6 hour range
  447. range: { from: moment(1443438674760), to: moment(1443460274760) },
  448. targets: [{
  449. expr: 'rate(test[$__interval])',
  450. interval: '10s'
  451. }],
  452. interval: '5s',
  453. scopedVars: {
  454. "__interval": {text: "5s", value: "5s"},
  455. "__interval_ms": {text: 5 * 1000, value: 5 * 1000},
  456. }
  457. };
  458. var urlExpected = 'proxied/api/v1/query_range?query=' +
  459. encodeURIComponent('rate(test[10s])') +
  460. '&start=1443438675&end=1443460275&step=10';
  461. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  462. ctx.ds.query(query);
  463. ctx.$httpBackend.verifyNoOutstandingExpectation();
  464. expect(query.scopedVars.__interval.text).to.be("5s");
  465. expect(query.scopedVars.__interval.value).to.be("5s");
  466. expect(query.scopedVars.__interval_ms.text).to.be(5 * 1000);
  467. expect(query.scopedVars.__interval_ms.value).to.be(5 * 1000);
  468. });
  469. it('should account for intervalFactor', function() {
  470. var query = {
  471. // 6 hour range
  472. range: { from: moment(1443438674760), to: moment(1443460274760) },
  473. targets: [{
  474. expr: 'rate(test[$__interval])',
  475. interval: '5s',
  476. intervalFactor: 10
  477. }],
  478. interval: '10s',
  479. scopedVars: {
  480. "__interval": {text: "10s", value: "10s"},
  481. "__interval_ms": {text: 10 * 1000, value: 10 * 1000},
  482. }
  483. };
  484. var urlExpected = 'proxied/api/v1/query_range?query=' +
  485. encodeURIComponent('rate(test[100s])') +
  486. '&start=1443438675&end=1443460275&step=100';
  487. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  488. ctx.ds.query(query);
  489. ctx.$httpBackend.verifyNoOutstandingExpectation();
  490. expect(query.scopedVars.__interval.text).to.be("10s");
  491. expect(query.scopedVars.__interval.value).to.be("10s");
  492. expect(query.scopedVars.__interval_ms.text).to.be(10 * 1000);
  493. expect(query.scopedVars.__interval_ms.value).to.be(10 * 1000);
  494. });
  495. it('should be interval * intervalFactor when greater than min interval', function() {
  496. var query = {
  497. // 6 hour range
  498. range: { from: moment(1443438674760), to: moment(1443460274760) },
  499. targets: [{
  500. expr: 'rate(test[$__interval])',
  501. interval: '10s',
  502. intervalFactor: 10
  503. }],
  504. interval: '5s',
  505. scopedVars: {
  506. "__interval": {text: "5s", value: "5s"},
  507. "__interval_ms": {text: 5 * 1000, value: 5 * 1000},
  508. }
  509. };
  510. var urlExpected = 'proxied/api/v1/query_range?query=' +
  511. encodeURIComponent('rate(test[50s])') +
  512. '&start=1443438675&end=1443460275&step=50';
  513. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  514. ctx.ds.query(query);
  515. ctx.$httpBackend.verifyNoOutstandingExpectation();
  516. expect(query.scopedVars.__interval.text).to.be("5s");
  517. expect(query.scopedVars.__interval.value).to.be("5s");
  518. expect(query.scopedVars.__interval_ms.text).to.be(5 * 1000);
  519. expect(query.scopedVars.__interval_ms.value).to.be(5 * 1000);
  520. });
  521. it('should be min interval when greater than interval * intervalFactor', function() {
  522. var query = {
  523. // 6 hour range
  524. range: { from: moment(1443438674760), to: moment(1443460274760) },
  525. targets: [{
  526. expr: 'rate(test[$__interval])',
  527. interval: '15s',
  528. intervalFactor: 2
  529. }],
  530. interval: '5s',
  531. scopedVars: {
  532. "__interval": {text: "5s", value: "5s"},
  533. "__interval_ms": {text: 5 * 1000, value: 5 * 1000},
  534. }
  535. };
  536. var urlExpected = 'proxied/api/v1/query_range?query=' +
  537. encodeURIComponent('rate(test[15s])') +
  538. '&start=1443438675&end=1443460275&step=15';
  539. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  540. ctx.ds.query(query);
  541. ctx.$httpBackend.verifyNoOutstandingExpectation();
  542. expect(query.scopedVars.__interval.text).to.be("5s");
  543. expect(query.scopedVars.__interval.value).to.be("5s");
  544. expect(query.scopedVars.__interval_ms.text).to.be(5 * 1000);
  545. expect(query.scopedVars.__interval_ms.value).to.be(5 * 1000);
  546. });
  547. it('should be determined by the 11000 data points limit, accounting for intervalFactor', function() {
  548. var query = {
  549. // 1 week range
  550. range: { from: moment(1443438674760), to: moment(1444043474760) },
  551. targets: [{
  552. expr: 'rate(test[$__interval])',
  553. intervalFactor: 10
  554. }],
  555. interval: '5s',
  556. scopedVars: {
  557. "__interval": {text: "5s", value: "5s"},
  558. "__interval_ms": {text: 5 * 1000, value: 5 * 1000},
  559. }
  560. };
  561. var urlExpected = 'proxied/api/v1/query_range?query=' +
  562. encodeURIComponent('rate(test[60s])') +
  563. '&start=1443438675&end=1444043475&step=60';
  564. ctx.$httpBackend.expect('GET', urlExpected).respond(response);
  565. ctx.ds.query(query);
  566. ctx.$httpBackend.verifyNoOutstandingExpectation();
  567. expect(query.scopedVars.__interval.text).to.be("5s");
  568. expect(query.scopedVars.__interval.value).to.be("5s");
  569. expect(query.scopedVars.__interval_ms.text).to.be(5 * 1000);
  570. expect(query.scopedVars.__interval_ms.value).to.be(5 * 1000);
  571. });
  572. });
  573. });