datasource_specs.ts 22 KB

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