datasource.jest.ts 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. import _ from 'lodash';
  2. import moment from 'moment';
  3. import angular from 'angular';
  4. import { ElasticDatasource } from '../datasource';
  5. import { TimeSrv } from 'app/features/dashboard/time_srv';
  6. import { TemplateSrv } from 'app/features/templating/template_srv';
  7. import $q from 'q';
  8. describe('ElasticDatasource', function() {
  9. let backendSrv = {
  10. datasourceRequest: jest.fn(),
  11. };
  12. let $rootScope = {
  13. $on: jest.fn(),
  14. appEvent: jest.fn(),
  15. };
  16. let templateSrv = new TemplateSrv();
  17. templateSrv.variables = [];
  18. let timeSrv = new TimeSrv($rootScope, jest.fn(), {}, {}, {});
  19. let ctx = <any>{
  20. $rootScope,
  21. backendSrv,
  22. $q,
  23. };
  24. function createDatasource(instanceSettings) {
  25. instanceSettings.jsonData = instanceSettings.jsonData || {};
  26. ctx.ds = new ElasticDatasource(instanceSettings, {}, backendSrv, templateSrv, timeSrv);
  27. }
  28. describe('When testing datasource with index pattern', function() {
  29. beforeEach(function() {
  30. createDatasource({
  31. url: 'http://es.com',
  32. index: '[asd-]YYYY.MM.DD',
  33. jsonData: { interval: 'Daily', esVersion: '2' },
  34. });
  35. });
  36. it('should translate index pattern to current day', function() {
  37. var requestOptions;
  38. ctx.backendSrv.datasourceRequest = jest.fn(options => {
  39. requestOptions = options;
  40. return Promise.resolve({ data: {} });
  41. });
  42. ctx.ds.testDatasource();
  43. var today = moment.utc().format('YYYY.MM.DD');
  44. expect(requestOptions.url).toBe('http://es.com/asd-' + today + '/_mapping');
  45. });
  46. });
  47. describe('When issuing metric query with interval pattern', function() {
  48. var requestOptions, parts, header;
  49. beforeEach(async () => {
  50. createDatasource({
  51. url: 'http://es.com',
  52. index: '[asd-]YYYY.MM.DD',
  53. jsonData: { interval: 'Daily', esVersion: '2' },
  54. });
  55. ctx.backendSrv.datasourceRequest = jest.fn(options => {
  56. requestOptions = options;
  57. return Promise.resolve({ data: { responses: [] } });
  58. });
  59. await ctx.ds.query({
  60. range: {
  61. from: moment.utc([2015, 4, 30, 10]),
  62. to: moment.utc([2015, 5, 1, 10]),
  63. },
  64. targets: [
  65. {
  66. bucketAggs: [],
  67. metrics: [{ type: 'raw_document' }],
  68. query: 'escape\\:test',
  69. },
  70. ],
  71. });
  72. parts = requestOptions.data.split('\n');
  73. header = angular.fromJson(parts[0]);
  74. });
  75. it('should translate index pattern to current day', function() {
  76. expect(header.index).toEqual(['asd-2015.05.30', 'asd-2015.05.31', 'asd-2015.06.01']);
  77. });
  78. it('should json escape lucene query', function() {
  79. var body = angular.fromJson(parts[1]);
  80. expect(body.query.bool.filter[1].query_string.query).toBe('escape\\:test');
  81. });
  82. });
  83. describe('When issuing document query', function() {
  84. var requestOptions, parts, header;
  85. beforeEach(function() {
  86. createDatasource({
  87. url: 'http://es.com',
  88. index: 'test',
  89. jsonData: { esVersion: '2' },
  90. });
  91. ctx.backendSrv.datasourceRequest = jest.fn(options => {
  92. requestOptions = options;
  93. return Promise.resolve({ data: { responses: [] } });
  94. });
  95. ctx.ds.query({
  96. range: {
  97. from: moment([2015, 4, 30, 10]),
  98. to: moment([2015, 5, 1, 10]),
  99. },
  100. targets: [
  101. {
  102. bucketAggs: [],
  103. metrics: [{ type: 'raw_document' }],
  104. query: 'test',
  105. },
  106. ],
  107. });
  108. parts = requestOptions.data.split('\n');
  109. header = angular.fromJson(parts[0]);
  110. });
  111. it('should set search type to query_then_fetch', function() {
  112. expect(header.search_type).toEqual('query_then_fetch');
  113. });
  114. it('should set size', function() {
  115. var body = angular.fromJson(parts[1]);
  116. expect(body.size).toBe(500);
  117. });
  118. });
  119. describe('When getting fields', function() {
  120. beforeEach(() => {
  121. createDatasource({ url: 'http://es.com', index: 'metricbeat' });
  122. ctx.backendSrv.datasourceRequest = jest.fn(options => {
  123. return Promise.resolve({
  124. data: {
  125. metricbeat: {
  126. mappings: {
  127. metricsets: {
  128. _all: {},
  129. properties: {
  130. '@timestamp': { type: 'date' },
  131. beat: {
  132. properties: {
  133. name: {
  134. fields: { raw: { type: 'keyword' } },
  135. type: 'string',
  136. },
  137. hostname: { type: 'string' },
  138. },
  139. },
  140. system: {
  141. properties: {
  142. cpu: {
  143. properties: {
  144. system: { type: 'float' },
  145. user: { type: 'float' },
  146. },
  147. },
  148. process: {
  149. properties: {
  150. cpu: {
  151. properties: {
  152. total: { type: 'float' },
  153. },
  154. },
  155. name: { type: 'string' },
  156. },
  157. },
  158. },
  159. },
  160. },
  161. },
  162. },
  163. },
  164. },
  165. });
  166. });
  167. });
  168. it('should return nested fields', function() {
  169. ctx.ds
  170. .getFields({
  171. find: 'fields',
  172. query: '*',
  173. })
  174. .then(fieldObjects => {
  175. var fields = _.map(fieldObjects, 'text');
  176. expect(fields).toEqual([
  177. '@timestamp',
  178. 'beat.name.raw',
  179. 'beat.name',
  180. 'beat.hostname',
  181. 'system.cpu.system',
  182. 'system.cpu.user',
  183. 'system.process.cpu.total',
  184. 'system.process.name',
  185. ]);
  186. });
  187. });
  188. it('should return fields related to query type', function() {
  189. ctx.ds
  190. .getFields({
  191. find: 'fields',
  192. query: '*',
  193. type: 'number',
  194. })
  195. .then(fieldObjects => {
  196. var fields = _.map(fieldObjects, 'text');
  197. expect(fields).toEqual(['system.cpu.system', 'system.cpu.user', 'system.process.cpu.total']);
  198. });
  199. ctx.ds
  200. .getFields({
  201. find: 'fields',
  202. query: '*',
  203. type: 'date',
  204. })
  205. .then(fieldObjects => {
  206. var fields = _.map(fieldObjects, 'text');
  207. expect(fields).toEqual(['@timestamp']);
  208. });
  209. });
  210. });
  211. describe('When issuing aggregation query on es5.x', function() {
  212. var requestOptions, parts, header;
  213. beforeEach(function() {
  214. createDatasource({
  215. url: 'http://es.com',
  216. index: 'test',
  217. jsonData: { esVersion: '5' },
  218. });
  219. ctx.backendSrv.datasourceRequest = jest.fn(options => {
  220. requestOptions = options;
  221. return Promise.resolve({ data: { responses: [] } });
  222. });
  223. ctx.ds.query({
  224. range: {
  225. from: moment([2015, 4, 30, 10]),
  226. to: moment([2015, 5, 1, 10]),
  227. },
  228. targets: [
  229. {
  230. bucketAggs: [{ type: 'date_histogram', field: '@timestamp', id: '2' }],
  231. metrics: [{ type: 'count' }],
  232. query: 'test',
  233. },
  234. ],
  235. });
  236. parts = requestOptions.data.split('\n');
  237. header = angular.fromJson(parts[0]);
  238. });
  239. it('should not set search type to count', function() {
  240. expect(header.search_type).not.toEqual('count');
  241. });
  242. it('should set size to 0', function() {
  243. var body = angular.fromJson(parts[1]);
  244. expect(body.size).toBe(0);
  245. });
  246. });
  247. describe('When issuing metricFind query on es5.x', function() {
  248. var requestOptions, parts, header, body, results;
  249. beforeEach(() => {
  250. createDatasource({
  251. url: 'http://es.com',
  252. index: 'test',
  253. jsonData: { esVersion: '5' },
  254. });
  255. ctx.backendSrv.datasourceRequest = jest.fn(options => {
  256. requestOptions = options;
  257. return Promise.resolve({
  258. data: {
  259. responses: [
  260. {
  261. aggregations: {
  262. '1': {
  263. buckets: [
  264. { doc_count: 1, key: 'test' },
  265. {
  266. doc_count: 2,
  267. key: 'test2',
  268. key_as_string: 'test2_as_string',
  269. },
  270. ],
  271. },
  272. },
  273. },
  274. ],
  275. },
  276. });
  277. });
  278. ctx.ds.metricFindQuery('{"find": "terms", "field": "test"}').then(res => {
  279. results = res;
  280. });
  281. parts = requestOptions.data.split('\n');
  282. header = angular.fromJson(parts[0]);
  283. body = angular.fromJson(parts[1]);
  284. });
  285. it('should get results', () => {
  286. expect(results.length).toEqual(2);
  287. });
  288. it('should use key or key_as_string', () => {
  289. expect(results[0].text).toEqual('test');
  290. expect(results[1].text).toEqual('test2_as_string');
  291. });
  292. it('should not set search type to count', () => {
  293. expect(header.search_type).not.toEqual('count');
  294. });
  295. it('should set size to 0', () => {
  296. expect(body.size).toBe(0);
  297. });
  298. it('should not set terms aggregation size to 0', () => {
  299. expect(body['aggs']['1']['terms'].size).not.toBe(0);
  300. });
  301. });
  302. });