grafana/public/app/core/services/FetchQueueWorker.test.ts
Hugo Häggmark 9e357d84a4
BackendSrv: Queues data source requests but passes through api requests (#26947)
* Refactor: initial commit

* wip

* Refactor: getting into a simpler model

* Refactor: adds some comments

* Refactor: renames statuses according to PR comments

* Refactor: adds more comments

* Tests: adds tests for FetchQueue

* Tests: adds tests for ResponseQueue

* Tests: adds tests for FetchQueueWorker

* Tests: simplified the tests for ResponseQueue

* Refactor: adds http2 scenario

* Refactor: using Cfg instead of global variable

Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com>

* Refactor: reverted change in frontendsettings.go

* Tests: fix test mocks

* Fix: changes how cfg.Protocol gets its value

Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com>
2020-08-20 11:32:10 +02:00

98 lines
3.7 KiB
TypeScript

import { Subject } from 'rxjs';
import { FetchQueue, FetchQueueUpdate, FetchStatus } from './FetchQueue';
import { ResponseQueue } from './ResponseQueue';
import { FetchQueueWorker } from './FetchQueueWorker';
import { expect } from '../../../test/lib/common';
import { GrafanaBootConfig } from '@grafana/runtime';
const getTestContext = (http2Enabled = false) => {
const config: GrafanaBootConfig = ({ http2Enabled } as unknown) as GrafanaBootConfig;
const dataUrl = 'http://localhost:3000/api/ds/query?=abc';
const apiUrl = 'http://localhost:3000/api/alerts?state=all';
const updates: Subject<FetchQueueUpdate> = new Subject<FetchQueueUpdate>();
const queueMock: FetchQueue = ({
add: jest.fn(),
setInProgress: jest.fn(),
setDone: jest.fn(),
getUpdates: () => updates.asObservable(),
} as unknown) as FetchQueue;
const addMock = jest.fn();
const responseQueueMock: ResponseQueue = ({
add: addMock,
getResponses: jest.fn(),
} as unknown) as ResponseQueue;
new FetchQueueWorker(queueMock, responseQueueMock, config);
return { dataUrl, apiUrl, updates, queueMock, addMock };
};
describe('FetchQueueWorker', () => {
describe('when an update is pushed in the stream', () => {
describe('and queue has no pending entries', () => {
it('then nothing should be added to the responseQueue', () => {
const { updates, addMock } = getTestContext();
updates.next({ noOfPending: 0, noOfInProgress: 1, state: {} });
expect(addMock).toHaveBeenCalledTimes(0);
});
});
describe('and queue has pending entries', () => {
describe('and there are no entries in progress', () => {
it('then api request should be added before data requests responseQueue', () => {
const { updates, addMock, dataUrl, apiUrl } = getTestContext();
updates.next({
noOfPending: 2,
noOfInProgress: 0,
state: {
['data']: { state: FetchStatus.Pending, options: { url: dataUrl } },
['api']: { state: FetchStatus.Pending, options: { url: apiUrl } },
},
});
expect(addMock.mock.calls).toEqual([
['api', { url: 'http://localhost:3000/api/alerts?state=all' }],
['data', { url: 'http://localhost:3000/api/ds/query?=abc' }],
]);
});
});
describe('and there are max concurrent entries in progress', () => {
it('then api request should always pass through but no data requests should pass', () => {
const { updates, addMock, dataUrl, apiUrl } = getTestContext();
updates.next({
noOfPending: 2,
noOfInProgress: 5,
state: {
['data']: { state: FetchStatus.Pending, options: { url: dataUrl } },
['api']: { state: FetchStatus.Pending, options: { url: apiUrl } },
},
});
expect(addMock.mock.calls).toEqual([['api', { url: 'http://localhost:3000/api/alerts?state=all' }]]);
});
});
describe('and http2 is enabled and there are max concurrent entries in progress', () => {
it('then api request should always pass through but no data requests should pass', () => {
const { updates, addMock, dataUrl, apiUrl } = getTestContext(true);
updates.next({
noOfPending: 2,
noOfInProgress: 1000,
state: {
['data']: { state: FetchStatus.Pending, options: { url: dataUrl } },
['api']: { state: FetchStatus.Pending, options: { url: apiUrl } },
},
});
expect(addMock.mock.calls).toEqual([['api', { url: 'http://localhost:3000/api/alerts?state=all' }]]);
});
});
});
});
});