mirror of
https://github.com/Unleash/unleash.git
synced 2025-09-10 17:53:36 +02:00
fix: more unit tests
This commit is contained in:
parent
30c7e6f78e
commit
fbdae0df0a
@ -82,6 +82,9 @@ export class ClientMetricsStoreV2 implements IClientMetricsStoreV2 {
|
|||||||
|
|
||||||
// this function will collapse metrics before sending it to the database.
|
// this function will collapse metrics before sending it to the database.
|
||||||
async batchInsertMetrics(metrics: IClientMetricsEnv[]): Promise<void> {
|
async batchInsertMetrics(metrics: IClientMetricsEnv[]): Promise<void> {
|
||||||
|
if (!metrics || metrics.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const rows = metrics.map(toRow);
|
const rows = metrics.map(toRow);
|
||||||
|
|
||||||
const batch = rows.reduce((prev, curr) => {
|
const batch = rows.reduce((prev, curr) => {
|
||||||
|
@ -8,6 +8,8 @@ import { IAuthRequest } from '../unleash-types';
|
|||||||
import ApiUser from '../../types/api-user';
|
import ApiUser from '../../types/api-user';
|
||||||
import { ALL } from '../../types/models/api-token';
|
import { ALL } from '../../types/models/api-token';
|
||||||
import ClientMetricsServiceV2 from '../../services/client-metrics/client-metrics-service-v2';
|
import ClientMetricsServiceV2 from '../../services/client-metrics/client-metrics-service-v2';
|
||||||
|
import { User } from '../../server-impl';
|
||||||
|
import { IClientApp } from '../../types/model';
|
||||||
|
|
||||||
export default class ClientMetricsController extends Controller {
|
export default class ClientMetricsController extends Controller {
|
||||||
logger: Logger;
|
logger: Logger;
|
||||||
@ -42,13 +44,20 @@ export default class ClientMetricsController extends Controller {
|
|||||||
this.post('/', this.registerMetrics);
|
this.post('/', this.registerMetrics);
|
||||||
}
|
}
|
||||||
|
|
||||||
async registerMetrics(req: IAuthRequest, res: Response): Promise<void> {
|
private resolveEnvironment(user: User, data: IClientApp) {
|
||||||
const { body: data, ip: clientIp, user } = req;
|
|
||||||
if (user instanceof ApiUser) {
|
if (user instanceof ApiUser) {
|
||||||
if (user.environment !== ALL) {
|
if (user.environment !== ALL) {
|
||||||
data.environment = user.environment;
|
return user.environment;
|
||||||
|
} else if (user.environment === ALL && data.environment) {
|
||||||
|
return data.environment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return 'default';
|
||||||
|
}
|
||||||
|
|
||||||
|
async registerMetrics(req: IAuthRequest, res: Response): Promise<void> {
|
||||||
|
const { body: data, ip: clientIp, user } = req;
|
||||||
|
data.environment = this.resolveEnvironment(user, data);
|
||||||
await this.metrics.registerClientMetrics(data, clientIp);
|
await this.metrics.registerClientMetrics(data, clientIp);
|
||||||
|
|
||||||
if (this.newServiceEnabled) {
|
if (this.newServiceEnabled) {
|
||||||
|
@ -258,6 +258,7 @@ export interface IClientApp {
|
|||||||
appName: string;
|
appName: string;
|
||||||
instanceId: string;
|
instanceId: string;
|
||||||
clientIp?: string;
|
clientIp?: string;
|
||||||
|
environment?: string;
|
||||||
seenToggles?: string[];
|
seenToggles?: string[];
|
||||||
metricsCount?: number;
|
metricsCount?: number;
|
||||||
strategies?: string[] | Record<string, string>[];
|
strategies?: string[] | Record<string, string>[];
|
||||||
|
@ -8,7 +8,7 @@ let db: ITestDb;
|
|||||||
const featureName = 'feature.default.1';
|
const featureName = 'feature.default.1';
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
db = await dbInit('feature_api_client', getLogger);
|
db = await dbInit('feature_env_api_client', getLogger);
|
||||||
app = await setupApp(db.stores);
|
app = await setupApp(db.stores);
|
||||||
|
|
||||||
await app.services.featureToggleServiceV2.createFeatureToggle(
|
await app.services.featureToggleServiceV2.createFeatureToggle(
|
||||||
|
@ -16,8 +16,7 @@ afterAll(async () => {
|
|||||||
await db.destroy();
|
await db.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should be possble to send metrics', async () => {
|
test('should be possible to send metrics', async () => {
|
||||||
expect.assertions(0);
|
|
||||||
return app.request
|
return app.request
|
||||||
.post('/api/client/metrics')
|
.post('/api/client/metrics')
|
||||||
.send(metricsExample)
|
.send(metricsExample)
|
||||||
@ -25,7 +24,6 @@ test('should be possble to send metrics', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should require valid send metrics', async () => {
|
test('should require valid send metrics', async () => {
|
||||||
expect.assertions(0);
|
|
||||||
return app.request
|
return app.request
|
||||||
.post('/api/client/metrics')
|
.post('/api/client/metrics')
|
||||||
.send({
|
.send({
|
||||||
@ -34,8 +32,7 @@ test('should require valid send metrics', async () => {
|
|||||||
.expect(400);
|
.expect(400);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should accept client metrics', async () => {
|
test('should accept empty client metrics', async () => {
|
||||||
expect.assertions(0);
|
|
||||||
return app.request
|
return app.request
|
||||||
.post('/api/client/metrics')
|
.post('/api/client/metrics')
|
||||||
.send({
|
.send({
|
||||||
|
100
src/test/e2e/api/client/metricsV2.e2e.test.ts
Normal file
100
src/test/e2e/api/client/metricsV2.e2e.test.ts
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
import { IUnleashTest, setupAppWithAuth } from '../../helpers/test-helper';
|
||||||
|
import metricsExample from '../../../examples/client-metrics.json';
|
||||||
|
import dbInit, { ITestDb } from '../../helpers/database-init';
|
||||||
|
import getLogger from '../../../fixtures/no-logger';
|
||||||
|
import { ApiTokenType } from '../../../../lib/types/models/api-token';
|
||||||
|
|
||||||
|
let app: IUnleashTest;
|
||||||
|
let db: ITestDb;
|
||||||
|
|
||||||
|
let defaultToken;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
db = await dbInit('metrics_two_api_client', getLogger);
|
||||||
|
app = await setupAppWithAuth(db.stores, {
|
||||||
|
experimental: { metricsV2: { enabled: true } },
|
||||||
|
});
|
||||||
|
defaultToken = await app.services.apiTokenService.createApiToken({
|
||||||
|
type: ApiTokenType.CLIENT,
|
||||||
|
project: 'default',
|
||||||
|
environment: 'default',
|
||||||
|
username: 'tester',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await db.stores.clientMetricsStoreV2.deleteAll();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await app.destroy();
|
||||||
|
await db.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should be possible to send metrics', async () => {
|
||||||
|
return app.request
|
||||||
|
.post('/api/client/metrics')
|
||||||
|
.set('Authorization', defaultToken.secret)
|
||||||
|
.send(metricsExample)
|
||||||
|
.expect(202);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should require valid send metrics', async () => {
|
||||||
|
return app.request
|
||||||
|
.post('/api/client/metrics')
|
||||||
|
.set('Authorization', defaultToken.secret)
|
||||||
|
.send({
|
||||||
|
appName: 'test',
|
||||||
|
})
|
||||||
|
.expect(400);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should accept client metrics', async () => {
|
||||||
|
return app.request
|
||||||
|
.post('/api/client/metrics')
|
||||||
|
.set('Authorization', defaultToken.secret)
|
||||||
|
.send({
|
||||||
|
appName: 'demo',
|
||||||
|
instanceId: '1',
|
||||||
|
bucket: {
|
||||||
|
start: Date.now(),
|
||||||
|
stop: Date.now(),
|
||||||
|
toggles: {},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.expect(202);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should pick up environment from token', async () => {
|
||||||
|
const environment = 'test';
|
||||||
|
await db.stores.environmentStore.create({ name: 'test', type: 'test' });
|
||||||
|
const token = await app.services.apiTokenService.createApiToken({
|
||||||
|
type: ApiTokenType.CLIENT,
|
||||||
|
project: 'default',
|
||||||
|
environment,
|
||||||
|
username: 'tester',
|
||||||
|
});
|
||||||
|
|
||||||
|
await app.request
|
||||||
|
.post('/api/client/metrics')
|
||||||
|
.set('Authorization', token.secret)
|
||||||
|
.send({
|
||||||
|
appName: 'some-fancy-app',
|
||||||
|
instanceId: '1',
|
||||||
|
bucket: {
|
||||||
|
start: Date.now(),
|
||||||
|
stop: Date.now(),
|
||||||
|
toggles: {
|
||||||
|
test: {
|
||||||
|
yes: 100,
|
||||||
|
no: 50,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.expect(202);
|
||||||
|
|
||||||
|
const metrics = await db.stores.clientMetricsStoreV2.getAll();
|
||||||
|
expect(metrics[0].environment).toBe('test');
|
||||||
|
expect(metrics[0].appName).toBe('some-fancy-app');
|
||||||
|
});
|
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
import supertest from 'supertest';
|
import supertest from 'supertest';
|
||||||
|
|
||||||
import EventEmitter from 'events';
|
import EventEmitter from 'events';
|
||||||
@ -62,7 +63,6 @@ export async function setupApp(stores: IUnleashStores): Promise<IUnleashTest> {
|
|||||||
|
|
||||||
export async function setupAppWithCustomConfig(
|
export async function setupAppWithCustomConfig(
|
||||||
stores: IUnleashStores,
|
stores: IUnleashStores,
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
||||||
customOptions: any,
|
customOptions: any,
|
||||||
): Promise<IUnleashTest> {
|
): Promise<IUnleashTest> {
|
||||||
return createApp(stores, undefined, undefined, customOptions);
|
return createApp(stores, undefined, undefined, customOptions);
|
||||||
@ -70,8 +70,9 @@ export async function setupAppWithCustomConfig(
|
|||||||
|
|
||||||
export async function setupAppWithAuth(
|
export async function setupAppWithAuth(
|
||||||
stores: IUnleashStores,
|
stores: IUnleashStores,
|
||||||
|
customOptions?: any,
|
||||||
): Promise<IUnleashTest> {
|
): Promise<IUnleashTest> {
|
||||||
return createApp(stores, IAuthType.DEMO);
|
return createApp(stores, IAuthType.DEMO, undefined, customOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setupAppWithCustomAuth(
|
export async function setupAppWithCustomAuth(
|
||||||
|
@ -248,3 +248,17 @@ test('Should return seen applications using a feature toggle', async () => {
|
|||||||
expect(apps).toHaveLength(2);
|
expect(apps).toHaveLength(2);
|
||||||
expect(apps).toStrictEqual(['backend-api', 'web']);
|
expect(apps).toStrictEqual(['backend-api', 'web']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Should not fail on empty list of metrics', async () => {
|
||||||
|
await clientMetricsStore.batchInsertMetrics([]);
|
||||||
|
const all = await clientMetricsStore.getAll();
|
||||||
|
|
||||||
|
expect(all).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Should not fail on undefined list of metrics', async () => {
|
||||||
|
await clientMetricsStore.batchInsertMetrics(undefined);
|
||||||
|
const all = await clientMetricsStore.getAll();
|
||||||
|
|
||||||
|
expect(all).toHaveLength(0);
|
||||||
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user