datasource_specs.ts 22 KB

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