mirror of
https://github.com/Unleash/unleash.git
synced 2025-11-10 01:19:53 +01:00
317 lines
9.2 KiB
TypeScript
317 lines
9.2 KiB
TypeScript
import dbInit, {
|
|
type ITestDb,
|
|
} from '../../../test/e2e/helpers/database-init.js';
|
|
import getLogger from '../../../test/fixtures/no-logger.js';
|
|
import type { FeatureToggleService } from '../../../lib/features/feature-toggle/feature-toggle-service.js';
|
|
import type ProjectService from '../../../lib/features/project/project-service.js';
|
|
import { createTestConfig } from '../../../test/config/test-config.js';
|
|
import type {
|
|
EventService,
|
|
ProjectInsightsService,
|
|
} from '../../../lib/services/index.js';
|
|
import { FeatureEnvironmentEvent } from '../../types/index.js';
|
|
import { subDays } from 'date-fns';
|
|
import {
|
|
createEventsService,
|
|
createFeatureToggleService,
|
|
createProjectService,
|
|
} from '../../../lib/features/index.js';
|
|
import {
|
|
type IUnleashStores,
|
|
type IUser,
|
|
TEST_AUDIT_USER,
|
|
} from '../../types/index.js';
|
|
import type { User } from '../../types/user.js';
|
|
import { createProjectInsightsService } from './createProjectInsightsService.js';
|
|
import { extractAuditInfoFromUser } from '../../util/index.js';
|
|
|
|
let stores: IUnleashStores;
|
|
let db: ITestDb;
|
|
|
|
let projectService: ProjectService;
|
|
let projectInsightsService: ProjectInsightsService;
|
|
let eventService: EventService;
|
|
let featureToggleService: FeatureToggleService;
|
|
let user: User; // many methods in this test use User instead of IUser
|
|
let opsUser: IUser;
|
|
|
|
beforeAll(async () => {
|
|
db = await dbInit('project_service_serial', getLogger);
|
|
stores = db.stores;
|
|
// @ts-ignore return type IUser type missing generateImageUrl
|
|
user = await stores.userStore.insert({
|
|
name: 'Some Name',
|
|
email: 'test@getunleash.io',
|
|
});
|
|
opsUser = await stores.userStore.insert({
|
|
name: 'Test user',
|
|
email: 'test@example.com',
|
|
});
|
|
const config = createTestConfig({
|
|
getLogger,
|
|
});
|
|
eventService = createEventsService(db.rawDatabase, config);
|
|
|
|
featureToggleService = createFeatureToggleService(db.rawDatabase, config);
|
|
|
|
projectService = createProjectService(db.rawDatabase, config);
|
|
|
|
projectInsightsService = createProjectInsightsService(
|
|
db.rawDatabase,
|
|
config,
|
|
);
|
|
});
|
|
|
|
afterAll(async () => {
|
|
await db.destroy();
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await stores.eventStore.deleteAll();
|
|
});
|
|
|
|
const updateFeature = async (featureName: string, update: any) => {
|
|
return db.rawDatabase
|
|
.table('features')
|
|
.update(update)
|
|
.where({ name: featureName });
|
|
};
|
|
|
|
test('should return average time to production per toggle', async () => {
|
|
const project = {
|
|
id: 'average-time-to-prod-per-toggle',
|
|
name: 'average-time-to-prod-per-toggle',
|
|
mode: 'open' as const,
|
|
defaultStickiness: 'clientId',
|
|
};
|
|
|
|
await projectService.createProject(
|
|
project,
|
|
user,
|
|
extractAuditInfoFromUser(user),
|
|
);
|
|
|
|
const toggles = [
|
|
{ name: 'average-prod-time-pt', subdays: 7 },
|
|
{ name: 'average-prod-time-pt-2', subdays: 14 },
|
|
{ name: 'average-prod-time-pt-3', subdays: 40 },
|
|
{ name: 'average-prod-time-pt-4', subdays: 15 },
|
|
{ name: 'average-prod-time-pt-5', subdays: 2 },
|
|
];
|
|
|
|
const featureToggles = await Promise.all(
|
|
toggles.map((toggle) => {
|
|
return featureToggleService.createFeatureToggle(
|
|
project.id,
|
|
toggle,
|
|
extractAuditInfoFromUser(opsUser),
|
|
);
|
|
}),
|
|
);
|
|
|
|
await Promise.all(
|
|
featureToggles.map((toggle) => {
|
|
return eventService.storeEvent(
|
|
new FeatureEnvironmentEvent({
|
|
enabled: true,
|
|
project: project.id,
|
|
featureName: toggle.name,
|
|
environment: 'production',
|
|
auditUser: TEST_AUDIT_USER,
|
|
}),
|
|
);
|
|
}),
|
|
);
|
|
|
|
await Promise.all(
|
|
toggles.map((toggle) =>
|
|
updateFeature(toggle.name, {
|
|
created_at: subDays(new Date(), toggle.subdays),
|
|
}),
|
|
),
|
|
);
|
|
|
|
const result = await projectInsightsService.getDoraMetrics(project.id);
|
|
|
|
expect(result.features).toHaveLength(5);
|
|
expect(result.features[0].timeToProduction).toBeTruthy();
|
|
expect(result.projectAverage).toBeTruthy();
|
|
});
|
|
|
|
test('should return average time to production per toggle for a specific project', async () => {
|
|
const project1 = {
|
|
id: 'average-time-to-prod-per-toggle-1',
|
|
name: 'Project 1',
|
|
mode: 'open' as const,
|
|
defaultStickiness: 'clientId',
|
|
};
|
|
|
|
const project2 = {
|
|
id: 'average-time-to-prod-per-toggle-2',
|
|
name: 'Project 2',
|
|
mode: 'open' as const,
|
|
defaultStickiness: 'clientId',
|
|
};
|
|
|
|
await projectService.createProject(
|
|
project1,
|
|
user,
|
|
extractAuditInfoFromUser(user),
|
|
);
|
|
await projectService.createProject(
|
|
project2,
|
|
user,
|
|
extractAuditInfoFromUser(user),
|
|
);
|
|
|
|
const togglesProject1 = [
|
|
{ name: 'average-prod-time-pt-10', subdays: 7 },
|
|
{ name: 'average-prod-time-pt-11', subdays: 14 },
|
|
{ name: 'average-prod-time-pt-12', subdays: 40 },
|
|
];
|
|
|
|
const togglesProject2 = [
|
|
{ name: 'average-prod-time-pt-13', subdays: 15 },
|
|
{ name: 'average-prod-time-pt-14', subdays: 2 },
|
|
];
|
|
|
|
const featureTogglesProject1 = await Promise.all(
|
|
togglesProject1.map((toggle) => {
|
|
return featureToggleService.createFeatureToggle(
|
|
project1.id,
|
|
toggle,
|
|
extractAuditInfoFromUser(opsUser),
|
|
);
|
|
}),
|
|
);
|
|
|
|
const featureTogglesProject2 = await Promise.all(
|
|
togglesProject2.map((toggle) => {
|
|
return featureToggleService.createFeatureToggle(
|
|
project2.id,
|
|
toggle,
|
|
extractAuditInfoFromUser(opsUser),
|
|
);
|
|
}),
|
|
);
|
|
|
|
await Promise.all(
|
|
featureTogglesProject1.map((toggle) => {
|
|
return eventService.storeEvent(
|
|
new FeatureEnvironmentEvent({
|
|
enabled: true,
|
|
project: project1.id,
|
|
featureName: toggle.name,
|
|
environment: 'production',
|
|
auditUser: TEST_AUDIT_USER,
|
|
}),
|
|
);
|
|
}),
|
|
);
|
|
|
|
await Promise.all(
|
|
featureTogglesProject2.map((toggle) => {
|
|
return eventService.storeEvent(
|
|
new FeatureEnvironmentEvent({
|
|
enabled: true,
|
|
project: project2.id,
|
|
featureName: toggle.name,
|
|
environment: 'production',
|
|
auditUser: TEST_AUDIT_USER,
|
|
}),
|
|
);
|
|
}),
|
|
);
|
|
|
|
await Promise.all(
|
|
togglesProject1.map((toggle) =>
|
|
updateFeature(toggle.name, {
|
|
created_at: subDays(new Date(), toggle.subdays),
|
|
}),
|
|
),
|
|
);
|
|
|
|
await Promise.all(
|
|
togglesProject2.map((toggle) =>
|
|
updateFeature(toggle.name, {
|
|
created_at: subDays(new Date(), toggle.subdays),
|
|
}),
|
|
),
|
|
);
|
|
|
|
const resultProject1 = await projectInsightsService.getDoraMetrics(
|
|
project1.id,
|
|
);
|
|
const resultProject2 = await projectInsightsService.getDoraMetrics(
|
|
project2.id,
|
|
);
|
|
|
|
expect(resultProject1.features).toHaveLength(3);
|
|
expect(resultProject2.features).toHaveLength(2);
|
|
});
|
|
|
|
test('should return average time to production per toggle and include archived toggles', async () => {
|
|
const project1 = {
|
|
id: 'average-time-to-prod-per-toggle-12',
|
|
name: 'Project 1',
|
|
mode: 'open' as const,
|
|
defaultStickiness: 'clientId',
|
|
};
|
|
|
|
await projectService.createProject(
|
|
project1,
|
|
user,
|
|
extractAuditInfoFromUser(user),
|
|
);
|
|
|
|
const togglesProject1 = [
|
|
{ name: 'average-prod-time-pta-10', subdays: 7 },
|
|
{ name: 'average-prod-time-pta-11', subdays: 14 },
|
|
{ name: 'average-prod-time-pta-12', subdays: 40 },
|
|
];
|
|
|
|
const featureTogglesProject1 = await Promise.all(
|
|
togglesProject1.map((toggle) => {
|
|
return featureToggleService.createFeatureToggle(
|
|
project1.id,
|
|
toggle,
|
|
extractAuditInfoFromUser(opsUser),
|
|
);
|
|
}),
|
|
);
|
|
|
|
await Promise.all(
|
|
featureTogglesProject1.map((toggle) => {
|
|
return eventService.storeEvent(
|
|
new FeatureEnvironmentEvent({
|
|
enabled: true,
|
|
project: project1.id,
|
|
featureName: toggle.name,
|
|
environment: 'production',
|
|
auditUser: TEST_AUDIT_USER,
|
|
}),
|
|
);
|
|
}),
|
|
);
|
|
|
|
await Promise.all(
|
|
togglesProject1.map((toggle) =>
|
|
updateFeature(toggle.name, {
|
|
created_at: subDays(new Date(), toggle.subdays),
|
|
}),
|
|
),
|
|
);
|
|
|
|
await featureToggleService.archiveToggle(
|
|
'average-prod-time-pta-12',
|
|
user,
|
|
extractAuditInfoFromUser(user),
|
|
);
|
|
|
|
const resultProject1 = await projectInsightsService.getDoraMetrics(
|
|
project1.id,
|
|
);
|
|
|
|
expect(resultProject1.features).toHaveLength(3);
|
|
});
|