1import LogAnalyticsQuerystringBuilder from './querystring_builder';
2import { dateTime } from '@grafana/data';
3
4describe('LogAnalyticsDatasource', () => {
5  let builder: LogAnalyticsQuerystringBuilder;
6
7  beforeEach(() => {
8    builder = new LogAnalyticsQuerystringBuilder(
9      'query=Tablename | where $__timeFilter()',
10      {
11        interval: '5m',
12        range: {
13          from: dateTime().subtract(24, 'hours'),
14          to: dateTime(),
15        },
16        rangeRaw: {
17          from: 'now-24h',
18          to: 'now',
19        },
20      },
21      'TimeGenerated'
22    );
23  });
24
25  describe('when $__timeFilter has no column parameter', () => {
26    it('should generate a time filter condition with TimeGenerated as the datetime field', () => {
27      const query = builder.generate().uriString;
28
29      expect(query).toContain('where%20TimeGenerated%20%3E%3D%20datetime(');
30    });
31  });
32
33  describe('when $__timeFilter has a column parameter', () => {
34    beforeEach(() => {
35      builder.rawQueryString = 'query=Tablename | where $__timeFilter(myTime)';
36    });
37
38    it('should generate a time filter condition with myTime as the datetime field', () => {
39      const query = builder.generate().uriString;
40
41      expect(query).toContain('where%20myTime%20%3E%3D%20datetime(');
42    });
43  });
44
45  describe('when $__contains and multi template variable has custom All value', () => {
46    beforeEach(() => {
47      builder.rawQueryString = 'query=Tablename | where $__contains(col, all)';
48    });
49
50    it('should generate a where..in clause', () => {
51      const query = builder.generate().rawQuery;
52
53      expect(query).toContain(`where 1 == 1`);
54    });
55  });
56
57  describe('when $__contains and multi template variable has one selected value', () => {
58    beforeEach(() => {
59      builder.rawQueryString = `query=Tablename | where $__contains(col, 'val1')`;
60    });
61
62    it('should generate a where..in clause', () => {
63      const query = builder.generate().rawQuery;
64
65      expect(query).toContain(`where col in ('val1')`);
66    });
67  });
68
69  describe('when $__contains and multi template variable has multiple selected values', () => {
70    beforeEach(() => {
71      builder.rawQueryString = `query=Tablename | where $__contains(col, 'val1','val2')`;
72    });
73
74    it('should generate a where..in clause', () => {
75      const query = builder.generate().rawQuery;
76
77      expect(query).toContain(`where col in ('val1','val2')`);
78    });
79  });
80
81  describe('when $__interval is in the query', () => {
82    beforeEach(() => {
83      builder.rawQueryString = 'query=Tablename | summarize count() by Category, bin(TimeGenerated, $__interval)';
84    });
85
86    it('should replace $__interval with the inbuilt interval option', () => {
87      const query = builder.generate().uriString;
88
89      expect(query).toContain('bin(TimeGenerated%2C%205m');
90    });
91  });
92
93  describe('when using $__timeFrom and $__timeTo is in the query and range is until now', () => {
94    beforeEach(() => {
95      builder.rawQueryString = 'query=Tablename | where myTime >= $__timeFrom() and myTime <= $__timeTo()';
96    });
97
98    it('should replace $__timeFrom and $__timeTo with a datetime and the now() function', () => {
99      const query = builder.generate().uriString;
100
101      expect(query).toContain('where%20myTime%20%3E%3D%20datetime(');
102      expect(query).toContain('myTime%20%3C%3D%20datetime(');
103    });
104  });
105
106  describe('when using $__timeFrom and $__timeTo is in the query and range is a specific interval', () => {
107    beforeEach(() => {
108      builder.rawQueryString = 'query=Tablename | where myTime >= $__timeFrom() and myTime <= $__timeTo()';
109      builder.options.range.to = dateTime().subtract(1, 'hour');
110      builder.options.rangeRaw.to = 'now-1h';
111    });
112
113    it('should replace $__timeFrom and $__timeTo with datetimes', () => {
114      const query = builder.generate().uriString;
115
116      expect(query).toContain('where%20myTime%20%3E%3D%20datetime(');
117      expect(query).toContain('myTime%20%3C%3D%20datetime(');
118    });
119  });
120
121  describe('when using $__escape and multi template variable has one selected value', () => {
122    beforeEach(() => {
123      builder.rawQueryString = `$__escapeMulti('\\grafana-vm\Network(eth0)\Total Bytes Received')`;
124    });
125
126    it('should replace $__escape(val) with KQL style escaped string', () => {
127      const query = builder.generate().uriString;
128      expect(query).toContain(`%40'%5Cgrafana-vmNetwork(eth0)Total%20Bytes%20Received'`);
129    });
130  });
131
132  describe('when using $__escape and multi template variable has multiple selected values', () => {
133    beforeEach(() => {
134      builder.rawQueryString = `CounterPath in ($__escapeMulti('\\grafana-vm\Network(eth0)\Total','\\grafana-vm\Network(eth0)\Total'))`;
135    });
136
137    it('should replace $__escape(val) with multiple KQL style escaped string', () => {
138      const query = builder.generate().uriString;
139      expect(query).toContain(
140        `CounterPath%20in%20(%40'%5Cgrafana-vmNetwork(eth0)Total'%2C%20%40'%5Cgrafana-vmNetwork(eth0)Total')`
141      );
142    });
143  });
144
145  describe('when using $__escape and multi template variable has one selected value that contains comma', () => {
146    beforeEach(() => {
147      builder.rawQueryString = `$__escapeMulti('\\grafana-vm,\Network(eth0)\Total Bytes Received')`;
148    });
149
150    it('should replace $__escape(val) with KQL style escaped string', () => {
151      const query = builder.generate().uriString;
152      expect(query).toContain(`%40'%5Cgrafana-vm%2CNetwork(eth0)Total%20Bytes%20Received'`);
153    });
154  });
155
156  describe(`when using $__escape and multi template variable value is not wrapped in single '`, () => {
157    beforeEach(() => {
158      builder.rawQueryString = `$__escapeMulti(\\grafana-vm,\Network(eth0)\Total Bytes Received)`;
159    });
160
161    it('should not replace macro', () => {
162      const query = builder.generate().uriString;
163      expect(query).toContain(`%24__escapeMulti(%5Cgrafana-vm%2CNetwork(eth0)Total%20Bytes%20Received)`);
164    });
165  });
166
167  describe('when there is no raw range', () => {
168    it('should still generate a time filter condition', () => {
169      builder = new LogAnalyticsQuerystringBuilder(
170        'query=Tablename | where $__timeFilter()',
171        {
172          interval: '5m',
173          range: {
174            from: dateTime().subtract(24, 'hours'),
175            to: dateTime(),
176          },
177        },
178        'TimeGenerated'
179      );
180      const query = builder.generate().uriString;
181
182      expect(query).toContain('where%20TimeGenerated%20%20%3E%3D%20datetime(');
183    });
184  });
185});
186