mirror of
https://github.com/Unleash/unleash.git
synced 2025-04-24 01:18:01 +02:00
tests: add more tests for the lifecycle avg calculation query (#8698)
This PR adds more tests to check a few more cases for the lifecycle calculation query. Specifically, it tests that: - If we don't have any data for a stage, we return `null`. - We filter on projects - It correctly takes `0` days into account when calculating averages.
This commit is contained in:
parent
5733f91347
commit
0a250a7526
@ -1,4 +1,4 @@
|
|||||||
import { addDays } from 'date-fns';
|
import { addDays, addMinutes } from 'date-fns';
|
||||||
import dbInit, { type ITestDb } from '../../../test/e2e/helpers/database-init';
|
import dbInit, { type ITestDb } from '../../../test/e2e/helpers/database-init';
|
||||||
import getLogger from '../../../test/fixtures/no-logger';
|
import getLogger from '../../../test/fixtures/no-logger';
|
||||||
import { ProjectLifecycleSummaryReadModel } from './project-lifecycle-summary-read-model';
|
import { ProjectLifecycleSummaryReadModel } from './project-lifecycle-summary-read-model';
|
||||||
@ -17,6 +17,12 @@ afterAll(async () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await db.stores.projectStore.deleteAll();
|
||||||
|
await db.stores.featureToggleStore.deleteAll();
|
||||||
|
await db.stores.featureLifecycleStore.deleteAll();
|
||||||
|
});
|
||||||
|
|
||||||
const updateFeatureStageDate = async (
|
const updateFeatureStageDate = async (
|
||||||
flagName: string,
|
flagName: string,
|
||||||
stage: string,
|
stage: string,
|
||||||
@ -30,22 +36,22 @@ const updateFeatureStageDate = async (
|
|||||||
|
|
||||||
describe('Average time calculation', () => {
|
describe('Average time calculation', () => {
|
||||||
test('it calculates the average time for each stage', async () => {
|
test('it calculates the average time for each stage', async () => {
|
||||||
const project1 = await db.stores.projectStore.create({
|
const project = await db.stores.projectStore.create({
|
||||||
name: 'project1',
|
name: 'project',
|
||||||
id: 'project1',
|
id: randomId(),
|
||||||
});
|
});
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
|
|
||||||
const flags = [
|
const flags = [
|
||||||
{ name: randomId(), offsets: [2, 5, 6, 10] },
|
{ name: randomId(), offsets: [2, 5, 6, 10] },
|
||||||
{ name: randomId(), offsets: [1, null, 4, 7] },
|
{ name: randomId(), offsets: [1, null, 4, 7] },
|
||||||
{ name: randomId(), offsets: [12, 25, 8, 9] },
|
{ name: randomId(), offsets: [12, 25, 0, 9] },
|
||||||
{ name: randomId(), offsets: [1, 2, 3, null] },
|
{ name: randomId(), offsets: [1, 2, 3, null] },
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const { name, offsets } of flags) {
|
for (const { name, offsets } of flags) {
|
||||||
const created = await db.stores.featureToggleStore.create(
|
const created = await db.stores.featureToggleStore.create(
|
||||||
project1.id,
|
project.id,
|
||||||
{
|
{
|
||||||
name,
|
name,
|
||||||
createdByUserId: 1,
|
createdByUserId: 1,
|
||||||
@ -79,27 +85,115 @@ describe('Average time calculation', () => {
|
|||||||
await updateFeatureStageDate(
|
await updateFeatureStageDate(
|
||||||
created.name,
|
created.name,
|
||||||
stage,
|
stage,
|
||||||
|
addMinutes(
|
||||||
addDays(now, offsetFromInitial),
|
addDays(now, offsetFromInitial),
|
||||||
|
1 * (index + 1),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const readModel = new ProjectLifecycleSummaryReadModel(db.rawDatabase);
|
const readModel = new ProjectLifecycleSummaryReadModel(db.rawDatabase);
|
||||||
|
|
||||||
const result = await readModel.getAverageTimeInEachStage(project1.id);
|
const result = await readModel.getAverageTimeInEachStage(project.id);
|
||||||
|
|
||||||
expect(result).toMatchObject({
|
expect(result).toMatchObject({
|
||||||
initial: 4, // (2 + 1 + 12 + 1) / 4 = 4
|
initial: 4, // (2 + 1 + 12 + 1) / 4 = 4
|
||||||
'pre-live': 9, // (5 + 25 + 2 + 4) / 4 = 9
|
'pre-live': 9, // (5 + 4 + 25 + 2) / 4 = 9
|
||||||
live: 6, // (6 + 8 + 3) / 3 ~= 5.67 ~= 6
|
live: 3, // (6 + 0 + 3) / 3 = 3
|
||||||
completed: 9, // (10 + 7 + 9) / 3 ~= 8.67 ~= 9
|
completed: 9, // (10 + 7 + 9) / 3 ~= 8.67 ~= 9
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('it returns `null` if it has no data for something', async () => {});
|
test('it returns `null` if it has no data for something', async () => {
|
||||||
test('it rounds to the nearest whole number', async () => {});
|
const project = await db.stores.projectStore.create({
|
||||||
test('it ignores flags in other projects', async () => {});
|
name: 'project',
|
||||||
test('it ignores flags in other projects', async () => {});
|
id: randomId(),
|
||||||
|
});
|
||||||
test("it ignores rows that don't have a next stage", async () => {});
|
const readModel = new ProjectLifecycleSummaryReadModel(db.rawDatabase);
|
||||||
|
|
||||||
|
const result1 = await readModel.getAverageTimeInEachStage(project.id);
|
||||||
|
|
||||||
|
expect(result1).toMatchObject({
|
||||||
|
initial: null,
|
||||||
|
'pre-live': null,
|
||||||
|
live: null,
|
||||||
|
completed: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
const flag = await db.stores.featureToggleStore.create(project.id, {
|
||||||
|
name: randomId(),
|
||||||
|
createdByUserId: 1,
|
||||||
|
});
|
||||||
|
await db.stores.featureLifecycleStore.insert([
|
||||||
|
{
|
||||||
|
feature: flag.name,
|
||||||
|
stage: 'initial',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
await db.stores.featureLifecycleStore.insert([
|
||||||
|
{
|
||||||
|
feature: flag.name,
|
||||||
|
stage: 'pre-live',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
await updateFeatureStageDate(
|
||||||
|
flag.name,
|
||||||
|
'pre-live',
|
||||||
|
addDays(new Date(), 5),
|
||||||
|
);
|
||||||
|
|
||||||
|
const result2 = await readModel.getAverageTimeInEachStage(project.id);
|
||||||
|
|
||||||
|
expect(result2).toMatchObject({
|
||||||
|
initial: 5,
|
||||||
|
'pre-live': null,
|
||||||
|
live: null,
|
||||||
|
completed: null,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it ignores flags in other projects', async () => {
|
||||||
|
const project = await db.stores.projectStore.create({
|
||||||
|
name: 'project',
|
||||||
|
id: randomId(),
|
||||||
|
});
|
||||||
|
const readModel = new ProjectLifecycleSummaryReadModel(db.rawDatabase);
|
||||||
|
|
||||||
|
const flag = await db.stores.featureToggleStore.create(project.id, {
|
||||||
|
name: randomId(),
|
||||||
|
createdByUserId: 1,
|
||||||
|
});
|
||||||
|
await db.stores.featureLifecycleStore.insert([
|
||||||
|
{
|
||||||
|
feature: flag.name,
|
||||||
|
stage: 'initial',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
await db.stores.featureLifecycleStore.insert([
|
||||||
|
{
|
||||||
|
feature: flag.name,
|
||||||
|
stage: 'pre-live',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
await updateFeatureStageDate(
|
||||||
|
flag.name,
|
||||||
|
'pre-live',
|
||||||
|
addDays(new Date(), 5),
|
||||||
|
);
|
||||||
|
|
||||||
|
const result =
|
||||||
|
await readModel.getAverageTimeInEachStage('some-other-project');
|
||||||
|
|
||||||
|
expect(result).toMatchObject({
|
||||||
|
initial: null,
|
||||||
|
'pre-live': null,
|
||||||
|
live: null,
|
||||||
|
completed: null,
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -38,10 +38,10 @@ export class ProjectLifecycleSummaryReadModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getAverageTimeInEachStage(projectId: string): Promise<{
|
async getAverageTimeInEachStage(projectId: string): Promise<{
|
||||||
initial: number;
|
initial: number | null;
|
||||||
'pre-live': number;
|
'pre-live': number | null;
|
||||||
live: number;
|
live: number | null;
|
||||||
completed: number;
|
completed: number | null;
|
||||||
}> {
|
}> {
|
||||||
const q = this.db
|
const q = this.db
|
||||||
.with(
|
.with(
|
||||||
@ -80,10 +80,10 @@ export class ProjectLifecycleSummaryReadModel
|
|||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
initial: 0,
|
initial: null,
|
||||||
'pre-live': 0,
|
'pre-live': null,
|
||||||
live: 0,
|
live: null,
|
||||||
completed: 0,
|
completed: null,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -294,7 +294,7 @@ const config: Config = {
|
|||||||
routeBasePath: '/',
|
routeBasePath: '/',
|
||||||
remarkPlugins: [[pluginNpm2Yarn, { sync: true }]],
|
remarkPlugins: [[pluginNpm2Yarn, { sync: true }]],
|
||||||
docItemComponent: '@theme/ApiItem',
|
docItemComponent: '@theme/ApiItem',
|
||||||
sidebarPath: './sidebars.ts'
|
sidebarPath: './sidebars.ts',
|
||||||
},
|
},
|
||||||
theme: {
|
theme: {
|
||||||
customCss: './src/css/custom.css',
|
customCss: './src/css/custom.css',
|
||||||
|
Loading…
Reference in New Issue
Block a user