Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / packages / metrics / tests / integration.test.ts
blobfc5f361a39d08fe85495e7a902aafb5d90d0bd65
1 import Counter from '../lib/Counter';
2 import Histogram from '../lib/Histogram';
3 import MetricsApi from '../lib/MetricsApi';
4 import MetricsBase from '../lib/MetricsBase';
5 import MetricsRequestService from '../lib/MetricsRequestService';
6 import type IMetricsRequestService from '../lib/types/IMetricsRequestService';
7 import type MetricSchema from '../lib/types/MetricSchema';
9 export const counterName = 'counter_name';
10 export const counterVersion = 1;
12 export const histogramName = 'histogram_name';
13 export const histogramVersion = 1;
15 class MetricsTest extends MetricsBase {
16     public counter: Counter<MetricSchema>;
18     public histogram: Histogram<MetricSchema>;
20     constructor(requestService: IMetricsRequestService) {
21         super(requestService);
23         this.counter = new Counter<MetricSchema>({ name: counterName, version: counterVersion }, this.requestService);
24         this.histogram = new Histogram<MetricSchema>(
25             { name: histogramName, version: histogramVersion },
26             this.requestService
27         );
28     }
31 const metricsApi = new MetricsApi();
32 const metricsRequestService = new MetricsRequestService(metricsApi, { reportMetrics: true });
33 const metrics = new MetricsTest(metricsRequestService);
35 const uid = 'uid';
36 const clientID = 'clientID';
37 const appVersion = 'appVersion';
39 metrics.init({
40     uid,
41     clientID,
42     appVersion,
43 });
45 const time = new Date('2020-01-01');
47 describe('metrics', () => {
48     beforeAll(() => {
49         jest.useFakeTimers();
50     });
52     beforeEach(() => {
53         fetchMock.resetMocks();
54         jest.clearAllTimers();
55         jest.setSystemTime(time);
56     });
58     afterAll(() => {
59         jest.useRealTimers();
60     });
62     describe('counter requests', () => {
63         it('uses the metrics v1 url', () => {
64             metrics.counter.increment({
65                 foo: 'bar',
66             });
68             const url = fetchMock.mock.lastCall?.[0];
70             expect(fetchMock).toHaveBeenCalledTimes(1);
71             expect(url).toBe('/api/data/v1/metrics');
72         });
74         it('makes a post request', async () => {
75             metrics.counter.increment({
76                 foo: 'bar',
77             });
79             const content = fetchMock.mock.lastCall?.[1];
81             expect(fetchMock).toHaveBeenCalledTimes(1);
82             expect(content?.method).toBe('post');
83         });
85         it('contains the correct headers', async () => {
86             metrics.counter.increment({
87                 foo: 'bar',
88             });
90             const content = fetchMock.mock.lastCall?.[1];
92             expect(fetchMock).toHaveBeenCalledTimes(1);
93             expect(content?.headers).toEqual({
94                 'content-type': 'application/json',
95                 priority: 'u=6',
96                 'x-pm-appversion': `${clientID}@${appVersion}-dev`,
97                 'x-pm-uid': uid,
98             });
99         });
101         it('sends the metric name', async () => {
102             metrics.counter.increment({
103                 foo: 'bar',
104             });
106             const content = fetchMock.mock.lastCall?.[1];
107             // @ts-ignore
108             const body = JSON.parse(content?.body);
110             expect(fetchMock).toHaveBeenCalledTimes(1);
111             expect(body.Metrics[0].Name).toEqual(counterName);
112         });
114         it('sends the metric version', async () => {
115             metrics.counter.increment({
116                 foo: 'bar',
117             });
119             const content = fetchMock.mock.lastCall?.[1];
120             // @ts-ignore
121             const body = JSON.parse(content?.body);
123             expect(fetchMock).toHaveBeenCalledTimes(1);
124             expect(body.Metrics[0].Version).toEqual(counterVersion);
125         });
127         it('uses the current time for the timestamp', async () => {
128             metrics.counter.increment({
129                 foo: 'bar',
130             });
132             const content = fetchMock.mock.lastCall?.[1];
133             // @ts-ignore
134             const body = JSON.parse(content?.body);
136             expect(fetchMock).toHaveBeenCalledTimes(1);
137             expect(body.Metrics[0].Timestamp).toEqual(time.getTime() / 1000);
138         });
140         it('sends Value as 1', async () => {
141             metrics.counter.increment({
142                 foo: 'bar',
143             });
145             const content = fetchMock.mock.lastCall?.[1];
146             // @ts-ignore
147             const body = JSON.parse(content?.body);
149             expect(fetchMock).toHaveBeenCalledTimes(1);
150             expect(body.Metrics[0].Data.Value).toBe(1);
151         });
153         it('sends labels', async () => {
154             const labels = {
155                 foo: 'bar',
156                 bar: 'foo',
157             };
158             metrics.counter.increment(labels);
160             const content = fetchMock.mock.lastCall?.[1];
161             // @ts-ignore
162             const body = JSON.parse(content?.body);
164             expect(fetchMock).toHaveBeenCalledTimes(1);
165             expect(body.Metrics[0].Data.Labels).toEqual(labels);
166         });
167     });
169     describe('histogram requests', () => {
170         it('uses the metrics v1 url', async () => {
171             metrics.histogram.observe({
172                 Labels: {
173                     foo: 'bar',
174                 },
175                 Value: 1,
176             });
178             const url = fetchMock.mock.lastCall?.[0];
180             expect(fetchMock).toHaveBeenCalledTimes(1);
181             expect(url).toBe('/api/data/v1/metrics');
182         });
184         it('makes a post request', async () => {
185             metrics.histogram.observe({
186                 Labels: {
187                     foo: 'bar',
188                 },
189                 Value: 1,
190             });
192             const content = fetchMock.mock.lastCall?.[1];
194             expect(fetchMock).toHaveBeenCalledTimes(1);
195             expect(content?.method).toBe('post');
196         });
198         it('contains the correct headers', async () => {
199             metrics.histogram.observe({
200                 Labels: {
201                     foo: 'bar',
202                 },
203                 Value: 1,
204             });
206             const content = fetchMock.mock.lastCall?.[1];
208             expect(fetchMock).toHaveBeenCalledTimes(1);
209             expect(content?.headers).toEqual({
210                 'content-type': 'application/json',
211                 priority: 'u=6',
212                 'x-pm-appversion': `${clientID}@${appVersion}-dev`,
213                 'x-pm-uid': uid,
214             });
215         });
217         it('sends the metric name', async () => {
218             metrics.histogram.observe({
219                 Labels: {
220                     foo: 'bar',
221                 },
222                 Value: 1,
223             });
225             const content = fetchMock.mock.lastCall?.[1];
226             // @ts-ignore
227             const body = JSON.parse(content?.body);
229             expect(fetchMock).toHaveBeenCalledTimes(1);
230             expect(body.Metrics[0].Name).toEqual(histogramName);
231         });
233         it('sends the metric version', async () => {
234             metrics.histogram.observe({
235                 Labels: {
236                     foo: 'bar',
237                 },
238                 Value: 1,
239             });
241             const content = fetchMock.mock.lastCall?.[1];
242             // @ts-ignore
243             const body = JSON.parse(content?.body);
245             expect(fetchMock).toHaveBeenCalledTimes(1);
246             expect(body.Metrics[0].Version).toEqual(histogramVersion);
247         });
249         it('uses the current time for the timestamp', async () => {
250             metrics.histogram.observe({
251                 Labels: {
252                     foo: 'bar',
253                 },
254                 Value: 1,
255             });
257             const content = fetchMock.mock.lastCall?.[1];
258             // @ts-ignore
259             const body = JSON.parse(content?.body);
261             expect(fetchMock).toHaveBeenCalledTimes(1);
262             expect(body.Metrics[0].Timestamp).toEqual(time.getTime() / 1000);
263         });
265         it('sends float Values', async () => {
266             const Value = 1.234;
267             metrics.histogram.observe({
268                 Labels: {
269                     foo: 'bar',
270                 },
271                 Value,
272             });
274             const content = fetchMock.mock.lastCall?.[1];
275             // @ts-ignore
276             const body = JSON.parse(content?.body);
278             expect(fetchMock).toHaveBeenCalledTimes(1);
279             expect(body.Metrics[0].Data.Value).toBe(Value);
280         });
282         it('sends Labels', async () => {
283             const Labels = {
284                 foo: 'bar',
285                 bar: 'foo',
286             };
287             metrics.histogram.observe({
288                 Labels,
289                 Value: 1,
290             });
292             const content = fetchMock.mock.lastCall?.[1];
293             // @ts-ignore
294             const body = JSON.parse(content?.body);
296             expect(fetchMock).toHaveBeenCalledTimes(1);
297             expect(body.Metrics[0].Data.Labels).toEqual(Labels);
298         });
299     });