1 import MetricsApi from '../lib/MetricsApi';
2 import MetricsRequestService from '../lib/MetricsRequestService';
3 import type MetricsRequest from '../lib/types/MetricsRequest';
5 jest.mock('../lib/MetricsApi');
6 const metricsApi = new MetricsApi();
8 const getMetricsRequest = (name: string): MetricsRequest => ({
15 const defaultMetricsRequest = getMetricsRequest('Name');
17 describe('MetricsRequestService', () => {
23 jest.clearAllTimers();
30 it('makes construct correct request', () => {
31 const requestService = new MetricsRequestService(metricsApi, { reportMetrics: true });
33 requestService.report(defaultMetricsRequest);
35 expect(metricsApi.fetch).toHaveBeenCalledTimes(1);
36 expect(metricsApi.fetch).toHaveBeenCalledWith('api/data/v1/metrics', {
38 body: JSON.stringify({ Metrics: [defaultMetricsRequest] }),
42 describe('report metrics', () => {
43 it('allows api calls if reportMetrics was set to true in constructor', () => {
44 const requestService = new MetricsRequestService(metricsApi, { reportMetrics: true });
46 requestService.report(defaultMetricsRequest);
48 expect(metricsApi.fetch).toHaveBeenCalledTimes(1);
51 it('disallows api calls if reportMetrics was set to false in constructor', () => {
52 const requestService = new MetricsRequestService(metricsApi, { reportMetrics: false });
54 requestService.report(defaultMetricsRequest);
56 expect(metricsApi.fetch).not.toHaveBeenCalled();
59 describe('setter', () => {
60 it('allows api calls if reportMetrics is set to true via setter', () => {
61 const requestService = new MetricsRequestService(metricsApi, { reportMetrics: false });
63 requestService.setReportMetrics(true);
64 requestService.report(defaultMetricsRequest);
66 expect(metricsApi.fetch).toHaveBeenCalledTimes(1);
69 it('disallows api calls if reportMetrics is set to false via setter', () => {
70 const requestService = new MetricsRequestService(metricsApi, { reportMetrics: true });
72 requestService.setReportMetrics(false);
73 requestService.report(defaultMetricsRequest);
75 expect(metricsApi.fetch).not.toHaveBeenCalled();
80 describe('batching', () => {
81 describe('batch parameters', () => {
82 it('does not batch if frequency is 0', () => {
83 const requestService = new MetricsRequestService(metricsApi, {
91 requestService.report(defaultMetricsRequest);
93 expect(metricsApi.fetch).toHaveBeenCalledTimes(1);
96 it('does not batch if frequency is negative', () => {
97 const requestService = new MetricsRequestService(metricsApi, {
105 requestService.report(defaultMetricsRequest);
107 expect(metricsApi.fetch).toHaveBeenCalledTimes(1);
110 it('does not batch if size is 0', () => {
111 const requestService = new MetricsRequestService(metricsApi, {
119 requestService.report(defaultMetricsRequest);
121 expect(metricsApi.fetch).toHaveBeenCalledTimes(1);
124 it('does not batch if size is negative', () => {
125 const requestService = new MetricsRequestService(metricsApi, {
133 requestService.report(defaultMetricsRequest);
135 expect(metricsApi.fetch).toHaveBeenCalledTimes(1);
138 it('batches if frequency and size are positive', () => {
139 const requestService = new MetricsRequestService(metricsApi, {
147 requestService.report(getMetricsRequest('Request 1'));
148 requestService.report(getMetricsRequest('Request 2'));
149 expect(metricsApi.fetch).not.toHaveBeenCalled();
151 jest.advanceTimersByTime(1);
152 expect(metricsApi.fetch).toHaveBeenCalledWith('api/data/v1/metrics', {
154 body: JSON.stringify({ Metrics: [getMetricsRequest('Request 1')] }),
157 jest.advanceTimersByTime(1);
158 expect(metricsApi.fetch).toHaveBeenCalledWith('api/data/v1/metrics', {
160 body: JSON.stringify({ Metrics: [getMetricsRequest('Request 2')] }),
165 it('delays api calls until frequency timeout has expired', () => {
166 const batchFrequency = 100;
168 const requestService = new MetricsRequestService(metricsApi, {
171 frequency: batchFrequency,
176 requestService.report(defaultMetricsRequest);
177 expect(metricsApi.fetch).not.toHaveBeenCalled();
179 // fast-forward time until 1 millisecond before it should be executed
180 jest.advanceTimersByTime(batchFrequency - 1);
181 expect(metricsApi.fetch).not.toHaveBeenCalled();
183 // fast-forward until 1st call should be executed
184 jest.advanceTimersByTime(1);
185 expect(metricsApi.fetch).toHaveBeenCalledTimes(1);
188 it('does not call api if there are no items to process', () => {
189 const batchFrequency = 100;
191 const requestService = new MetricsRequestService(metricsApi, {
194 frequency: batchFrequency,
198 requestService.startBatchingProcess();
200 jest.advanceTimersByTime(batchFrequency);
201 expect(metricsApi.fetch).not.toHaveBeenCalled();
204 it('batches calls in order they were reported', () => {
205 const batchFrequency = 100;
207 const requestService = new MetricsRequestService(metricsApi, {
210 frequency: batchFrequency,
215 requestService.report(getMetricsRequest('Request 1'));
216 requestService.report(getMetricsRequest('Request 2'));
217 requestService.report(getMetricsRequest('Request 3'));
218 requestService.report(getMetricsRequest('Request 4'));
219 expect(metricsApi.fetch).not.toHaveBeenCalled();
221 jest.advanceTimersByTime(batchFrequency);
222 expect(metricsApi.fetch).toHaveBeenCalledWith('api/data/v1/metrics', {
224 body: JSON.stringify({ Metrics: [getMetricsRequest('Request 1'), getMetricsRequest('Request 2')] }),
227 jest.advanceTimersByTime(batchFrequency);
228 expect(metricsApi.fetch).toHaveBeenCalledWith('api/data/v1/metrics', {
230 body: JSON.stringify({ Metrics: [getMetricsRequest('Request 3'), getMetricsRequest('Request 4')] }),
234 it('handles partial batches', () => {
235 const batchFrequency = 100;
237 const requestService = new MetricsRequestService(metricsApi, {
240 frequency: batchFrequency,
245 requestService.report(getMetricsRequest('Request 1'));
246 requestService.report(getMetricsRequest('Request 2'));
247 requestService.report(getMetricsRequest('Request 3'));
248 expect(metricsApi.fetch).not.toHaveBeenCalled();
250 jest.advanceTimersByTime(batchFrequency);
251 expect(metricsApi.fetch).toHaveBeenCalledWith('api/data/v1/metrics', {
253 body: JSON.stringify({ Metrics: [getMetricsRequest('Request 1'), getMetricsRequest('Request 2')] }),
256 jest.advanceTimersByTime(batchFrequency);
257 expect(metricsApi.fetch).toHaveBeenCalledWith('api/data/v1/metrics', {
259 body: JSON.stringify({ Metrics: [getMetricsRequest('Request 3')] }),
264 describe('startBatchingProcess', () => {
265 it('starts batching interval on first report call if batch params are defined', () => {
266 const requestService = new MetricsRequestService(metricsApi, {
274 requestService.report(defaultMetricsRequest);
275 expect(metricsApi.fetch).not.toHaveBeenCalled();
277 jest.advanceTimersByTime(1);
278 expect(metricsApi.fetch).toHaveBeenCalledTimes(1);
281 it('does not set batching interval if no batch params are set', () => {
282 const requestService = new MetricsRequestService(metricsApi, {
286 requestService.report(defaultMetricsRequest);
287 expect(metricsApi.fetch).toHaveBeenCalledTimes(1);
290 * Advance timers to when call should have been
291 * performed if batching was enabled and ensure
292 * no extra calls have been made
294 jest.advanceTimersByTime(1);
295 expect(metricsApi.fetch).toHaveBeenCalledTimes(1);
299 describe('stopBatchingProcess', () => {
300 it('stops any further batch requests from occurring until startBatchingProcess is called', () => {
301 const requestService = new MetricsRequestService(metricsApi, {
309 requestService.report(defaultMetricsRequest);
310 requestService.report(defaultMetricsRequest);
311 expect(metricsApi.fetch).not.toHaveBeenCalled();
313 jest.advanceTimersByTime(1);
314 expect(metricsApi.fetch).toHaveBeenCalledTimes(1);
316 requestService.stopBatchingProcess();
318 jest.advanceTimersByTime(4);
319 expect(metricsApi.fetch).toHaveBeenCalledTimes(1);
321 requestService.startBatchingProcess();
323 jest.advanceTimersByTime(1);
324 expect(metricsApi.fetch).toHaveBeenCalledTimes(2);
328 describe('processAllRequests', () => {
329 it('does not make a request if there is no queue', async () => {
330 const batchFrequency = 10;
331 const requestService = new MetricsRequestService(metricsApi, {
334 frequency: batchFrequency,
339 await requestService.processAllRequests();
340 expect(metricsApi.fetch).not.toHaveBeenCalled();
343 it('processes all requests in queue regardless of batch size', async () => {
344 const batchFrequency = 10;
345 const requestService = new MetricsRequestService(metricsApi, {
348 frequency: batchFrequency,
353 requestService.report(getMetricsRequest('Request 1'));
354 requestService.report(getMetricsRequest('Request 2'));
355 requestService.report(getMetricsRequest('Request 3'));
356 expect(metricsApi.fetch).not.toHaveBeenCalled();
358 jest.advanceTimersByTime(batchFrequency);
359 expect(metricsApi.fetch).toHaveBeenCalledWith('api/data/v1/metrics', {
361 body: JSON.stringify({ Metrics: [getMetricsRequest('Request 1')] }),
364 jest.advanceTimersByTime(1);
365 await requestService.processAllRequests();
367 expect(metricsApi.fetch).toHaveBeenCalledTimes(2);
368 expect(metricsApi.fetch).toHaveBeenCalledWith('api/data/v1/metrics', {
370 body: JSON.stringify({ Metrics: [getMetricsRequest('Request 2'), getMetricsRequest('Request 3')] }),
374 it('clears queue', async () => {
375 const batchFrequency = 10;
376 const requestService = new MetricsRequestService(metricsApi, {
379 frequency: batchFrequency,
384 requestService.report(getMetricsRequest('Request 1'));
385 requestService.report(getMetricsRequest('Request 2'));
386 requestService.report(getMetricsRequest('Request 3'));
387 expect(metricsApi.fetch).not.toHaveBeenCalled();
389 await requestService.processAllRequests();
390 expect(metricsApi.fetch).toHaveBeenCalledTimes(1);
392 jest.advanceTimersByTime(batchFrequency);
393 expect(metricsApi.fetch).toHaveBeenCalledTimes(1);
397 describe('clearQueue', () => {
398 it('removes all items from queue', () => {
399 const batchFrequency = 10;
400 const requestService = new MetricsRequestService(metricsApi, {
403 frequency: batchFrequency,
408 requestService.report(getMetricsRequest('Request 1'));
409 requestService.report(getMetricsRequest('Request 2'));
410 requestService.report(getMetricsRequest('Request 3'));
411 expect(metricsApi.fetch).not.toHaveBeenCalled();
413 jest.advanceTimersByTime(batchFrequency);
414 expect(metricsApi.fetch).toHaveBeenCalledTimes(1);
416 requestService.clearQueue();
418 jest.advanceTimersByTime(batchFrequency);
419 expect(metricsApi.fetch).toHaveBeenCalledTimes(1);