Skip to content

Commit

Permalink
x-api-key-strategy-tests impl
Browse files Browse the repository at this point in the history
  • Loading branch information
sszafGCA committed Nov 14, 2023
1 parent caf07ab commit b040876
Show file tree
Hide file tree
Showing 2 changed files with 170 additions and 0 deletions.
160 changes: 160 additions & 0 deletions apps/server/src/apps/helpers/admin-api-setup-helper.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import { createMock } from '@golevelup/ts-jest';
import { Configuration } from '@hpi-schul-cloud/commons';
import { IConfig } from '@hpi-schul-cloud/commons/lib/interfaces/IConfig';
import {
PrometheusMetricsConfig,
createAPIResponseTimeMetricMiddleware,
createPrometheusMetricsApp,
} from '@infra/metrics';
import { Logger } from '@src/core/logger';
import express, { Express, NextFunction, Request, RequestHandler, Response } from 'express';
import {
PrometheusMetricsSetupState,
PrometheusMetricsSetupStateLoggable,
addPrometheusMetricsMiddlewaresIfEnabled,
createAndStartPrometheusMetricsAppIfEnabled,
} from './prometheus-metrics';

jest.mock('@infra/metrics', () => {
const moduleMock: unknown = {
...jest.requireActual('@infra/metrics'),
createAPIResponseTimeMetricMiddleware: jest.fn(),
createPrometheusMetricsApp: jest.fn(),
};

return moduleMock;
});

const testLogger = createMock<Logger>();

let configBefore: IConfig;

beforeAll(() => {
configBefore = Configuration.toObject({ plainSecrets: true });
});

beforeEach(() => {
Configuration.reset(configBefore);

const middlewareMock: RequestHandler = (_req: Request, _res: Response, next: NextFunction) => {
next();
};

(createAPIResponseTimeMetricMiddleware as jest.Mock).mockClear();
(createAPIResponseTimeMetricMiddleware as jest.Mock).mockReturnValue(middlewareMock);

const appMock = { listen: jest.fn() };

(createPrometheusMetricsApp as jest.Mock).mockClear();
(createPrometheusMetricsApp as jest.Mock).mockReturnValue(appMock);
});

afterAll(() => {
Configuration.reset(configBefore);
});

describe('PrometheusMetricsSetupStateLoggable', () => {
describe('getLogMessage', () => {
describe('should return a log message with proper content', () => {
const expectedMessage = 'Setting up Prometheus metrics...';

it.each([
[PrometheusMetricsSetupState.FEATURE_DISABLED_MIDDLEWARES_WILL_NOT_BE_CREATED],
[PrometheusMetricsSetupState.API_RESPONSE_TIME_METRIC_MIDDLEWARE_SUCCESSFULLY_ADDED],
[PrometheusMetricsSetupState.FEATURE_DISABLED_APP_WILL_NOT_BE_CREATED],
[PrometheusMetricsSetupState.COLLECTING_DEFAULT_METRICS_DISABLED],
[PrometheusMetricsSetupState.COLLECTING_METRICS_ROUTE_METRICS_DISABLED],
])("for the '%s' state", (state: PrometheusMetricsSetupState) => {
const testLogMessage = new PrometheusMetricsSetupStateLoggable(state).getLogMessage();

expect(testLogMessage).toHaveProperty('message', expectedMessage);
expect(testLogMessage).toHaveProperty('data', { state });
});
});
});
});

describe('addPrometheusMetricsMiddlewaresIfEnabled', () => {
let testApp: Express;
let testAppUseSpy: jest.SpyInstance;

beforeEach(() => {
testApp = express();
testAppUseSpy = jest.spyOn(testApp, 'use');
});

it('should create the API response time metric middleware and should add it to the given app', () => {
// To not create setters in the PrometheusMetricsConfig just for the unit tests
// purpose, we will enable the Prometheus metrics feature the way it should be
// enabled in a real app which is via the app configuration.
Configuration.set('FEATURE_PROMETHEUS_METRICS_ENABLED', true);
PrometheusMetricsConfig.reload();

addPrometheusMetricsMiddlewaresIfEnabled(testLogger, testApp);

expect(createAPIResponseTimeMetricMiddleware).toBeCalled();
expect(testAppUseSpy).toBeCalled();
});

it('should not create the API response time metric middleware and should not add it to the given app', () => {
Configuration.set('FEATURE_PROMETHEUS_METRICS_ENABLED', false);
PrometheusMetricsConfig.reload();

addPrometheusMetricsMiddlewaresIfEnabled(testLogger, testApp);

expect(createAPIResponseTimeMetricMiddleware).not.toBeCalled();
expect(testAppUseSpy).not.toBeCalled();
});
});

describe('createAndStartAdminApiServer', () => {
describe('should create Prometheus metrics app and run it', () => {
const testPort = 9000;
const testLoggerSpy = jest.spyOn(testLogger, 'info');

let appMockListenFn: jest.Mock;

beforeEach(() => {
testLoggerSpy.mockClear();
appMockListenFn = jest.fn();

(createPrometheusMetricsApp as jest.Mock).mockClear();
(createPrometheusMetricsApp as jest.Mock).mockReturnValue({ listen: appMockListenFn });
});

it.each([
[true, true],
[false, false],
[true, false],
[false, true],
])(
"with collecting default metrics set to '%s' and collecting metrics route metrics set to '%s'",
(collectDefaultMetrics: boolean, collectMetricsRouteMetrics: boolean) => {
Configuration.set('FEATURE_PROMETHEUS_METRICS_ENABLED', true);
Configuration.set('PROMETHEUS_METRICS_PORT', testPort);
Configuration.set('PROMETHEUS_METRICS_COLLECT_DEFAULT_METRICS', collectDefaultMetrics);
Configuration.set('PROMETHEUS_METRICS_COLLECT_METRICS_ROUTE_METRICS', collectMetricsRouteMetrics);
PrometheusMetricsConfig.reload();

createAndStartPrometheusMetricsAppIfEnabled(testLogger);

expect(createPrometheusMetricsApp).toBeCalledTimes(1);
expect(appMockListenFn).toHaveBeenLastCalledWith(testPort, expect.any(Function));

// Also test logging info message about running Prometheus metrics app.
// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
appMockListenFn.mock.lastCall[1]();
expect(testLoggerSpy).toBeCalledTimes(1);
}
);
});

it('should not create Prometheus metrics app if the whole feature is not enabled', () => {
Configuration.set('FEATURE_PROMETHEUS_METRICS_ENABLED', false);
PrometheusMetricsConfig.reload();

createAndStartPrometheusMetricsAppIfEnabled(testLogger);

expect(createPrometheusMetricsApp).not.toBeCalled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { IXApiKeyConfig } from '../config/x-api-key.config';
describe('XApiKeyStrategy', () => {
let module: TestingModule;
let strategy: XApiKeyStrategy;
let configService: ConfigService<IXApiKeyConfig, true>;
Configuration.set('ADMIN_API__ALLOWED_API_KEYS', '1ab2c3d4e5f61ab2c3d4e5f6');

beforeAll(async () => {
Expand All @@ -29,6 +30,7 @@ describe('XApiKeyStrategy', () => {
}).compile();

strategy = module.get(XApiKeyStrategy);
configService = module.get(ConfigService<IXApiKeyConfig, true>);
});

afterAll(async () => {
Expand Down Expand Up @@ -64,4 +66,12 @@ describe('XApiKeyStrategy', () => {
});
});
});

describe('constructor', () => {
it('should create strategy', () => {
const ApiKeyStrategy = new XApiKeyStrategy(configService);
expect(ApiKeyStrategy).toBeDefined();
expect(ApiKeyStrategy).toBeInstanceOf(XApiKeyStrategy);
});
});
});

0 comments on commit b040876

Please sign in to comment.