1import { getDefaultTimeRange } from '@grafana/data';
2
3import { AnnotationsQueryRunner } from './AnnotationsQueryRunner';
4import { AnnotationQueryRunnerOptions } from './types';
5import { silenceConsoleOutput } from '../../../../../test/core/utils/silenceConsoleOutput';
6import * as store from '../../../../store/store';
7import * as annotationsSrv from '../../../annotations/executeAnnotationQuery';
8import { Observable, of, throwError } from 'rxjs';
9import { toAsyncOfResult } from './testHelpers';
10
11function getDefaultOptions(): AnnotationQueryRunnerOptions {
12  const annotation: any = {};
13  const dashboard: any = {};
14  const datasource: any = {
15    annotationQuery: {},
16    annotations: {},
17  };
18  const range = getDefaultTimeRange();
19
20  return { annotation, datasource, dashboard, range };
21}
22
23function getTestContext(result: Observable<any> = toAsyncOfResult({ events: [{ id: '1' }] })) {
24  jest.clearAllMocks();
25  const dispatchMock = jest.spyOn(store, 'dispatch');
26  const options = getDefaultOptions();
27  const executeAnnotationQueryMock = jest.spyOn(annotationsSrv, 'executeAnnotationQuery').mockReturnValue(result);
28
29  return { options, dispatchMock, executeAnnotationQueryMock };
30}
31
32describe('AnnotationsQueryRunner', () => {
33  const runner = new AnnotationsQueryRunner();
34
35  describe('when canWork is called with correct props', () => {
36    it('then it should return true', () => {
37      const datasource: any = {
38        annotationQuery: jest.fn(),
39        annotations: {},
40      };
41
42      expect(runner.canRun(datasource)).toBe(true);
43    });
44  });
45
46  describe('when canWork is called without datasource', () => {
47    it('then it should return false', () => {
48      const datasource: any = undefined;
49
50      expect(runner.canRun(datasource)).toBe(false);
51    });
52  });
53
54  describe('when canWork is called with incorrect props', () => {
55    it('then it should return false', () => {
56      const datasource: any = {
57        annotationQuery: jest.fn(),
58      };
59
60      expect(runner.canRun(datasource)).toBe(false);
61    });
62  });
63
64  describe('when run is called with unsupported props', () => {
65    it('then it should return the correct results', async () => {
66      const datasource: any = {
67        annotationQuery: jest.fn(),
68      };
69      const { options, executeAnnotationQueryMock } = getTestContext();
70
71      await expect(runner.run({ ...options, datasource })).toEmitValuesWith((received) => {
72        expect(received).toHaveLength(1);
73        const results = received[0];
74        expect(results).toEqual([]);
75        expect(executeAnnotationQueryMock).toHaveBeenCalledTimes(0);
76      });
77    });
78  });
79
80  describe('when run is called and the request is successful', () => {
81    it('then it should return the correct results', async () => {
82      const { options, executeAnnotationQueryMock } = getTestContext();
83
84      await expect(runner.run(options)).toEmitValuesWith((received) => {
85        expect(received).toHaveLength(1);
86        const results = received[0];
87        expect(results).toEqual([{ id: '1' }]);
88        expect(executeAnnotationQueryMock).toHaveBeenCalledTimes(1);
89      });
90    });
91
92    describe('but result is missing events prop', () => {
93      it('then it should return the correct results', async () => {
94        const { options, executeAnnotationQueryMock } = getTestContext(of({ id: '1' }));
95
96        await expect(runner.run(options)).toEmitValuesWith((received) => {
97          expect(received).toHaveLength(1);
98          const results = received[0];
99          expect(results).toEqual([]);
100          expect(executeAnnotationQueryMock).toHaveBeenCalledTimes(1);
101        });
102      });
103    });
104  });
105
106  describe('when run is called and the request fails', () => {
107    silenceConsoleOutput();
108    it('then it should return the correct results', async () => {
109      const { options, executeAnnotationQueryMock, dispatchMock } = getTestContext(throwError({ message: 'An error' }));
110
111      await expect(runner.run(options)).toEmitValuesWith((received) => {
112        expect(received).toHaveLength(1);
113        const results = received[0];
114        expect(results).toEqual([]);
115        expect(executeAnnotationQueryMock).toHaveBeenCalledTimes(1);
116        expect(dispatchMock).toHaveBeenCalledTimes(1);
117      });
118    });
119  });
120
121  describe('when run is called and the request is cancelled', () => {
122    silenceConsoleOutput();
123    it('then it should return the correct results', async () => {
124      const { options, executeAnnotationQueryMock, dispatchMock } = getTestContext(throwError({ cancelled: true }));
125
126      await expect(runner.run(options)).toEmitValuesWith((received) => {
127        expect(received).toHaveLength(1);
128        const results = received[0];
129        expect(results).toEqual([]);
130        expect(executeAnnotationQueryMock).toHaveBeenCalledTimes(1);
131        expect(dispatchMock).not.toHaveBeenCalled();
132      });
133    });
134  });
135});
136