1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-23 00:22:19 +01:00

fix: onboarding events corner cases (#8057)

This commit is contained in:
Mateusz Kwasniewski 2024-09-03 12:53:48 +02:00 committed by GitHub
parent 08d9b92e55
commit b350bd11a7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 60 additions and 1 deletions

View File

@ -302,6 +302,7 @@ class UserStore implements IUserStore {
async getFirstUserDate(): Promise<Date | null> {
const firstInstanceUser = await this.db('users')
.select('created_at')
.where('is_system', '=', false)
.orderBy('created_at', 'asc')
.first();

View File

@ -35,9 +35,60 @@ beforeEach(async () => {
await stores.featureToggleStore.deleteAll();
await stores.projectStore.deleteAll();
await stores.onboardingStore.deleteAll();
await stores.userStore.deleteAll();
jest.useRealTimers();
});
test('Default project should take first user created instead of project created as start time', async () => {
jest.useFakeTimers();
jest.setSystemTime(new Date());
const { userStore, featureToggleStore, projectStore, projectReadModel } =
stores;
// default projects are created in advance and should be ignored
await projectStore.create({ id: 'default', name: 'irrelevant' });
jest.advanceTimersByTime(minutesToMilliseconds(1));
const user = await userStore.insert({});
await featureToggleStore.create('default', {
name: 'test-default',
createdByUserId: user.id,
});
jest.advanceTimersByTime(minutesToMilliseconds(1));
await onboardingService.insert({
type: 'flag-created',
flag: 'test-default',
});
await onboardingService.insert({ type: 'pre-live', flag: 'test-default' });
await onboardingService.insert({ type: 'live', flag: 'test-default' });
const { rows: projectEvents } = await db.rawDatabase.raw(
'SELECT * FROM onboarding_events_project',
);
expect(projectEvents).toMatchObject([
{ event: 'first-flag', time_to_event: 60, project: 'default' },
{
event: 'first-pre-live',
time_to_event: 60,
project: 'default',
},
{ event: 'first-live', time_to_event: 60, project: 'default' },
]);
});
test('Ignore system user in onboarding events', async () => {
// system users are not counted towards onboarding metrics
await db.rawDatabase.raw('INSERT INTO users (is_system) VALUES (true)');
await onboardingService.insert({ type: 'first-user-login' });
const { rows: instanceEvents } = await db.rawDatabase.raw(
'SELECT * FROM onboarding_events_instance',
);
expect(instanceEvents).toMatchObject([]);
});
test('Storing onboarding events', async () => {
jest.useFakeTimers();
jest.setSystemTime(new Date());

View File

@ -124,8 +124,15 @@ export class OnboardingService {
);
if (!project) return;
const startDate =
project.project === 'default'
? await this.userStore.getFirstUserDate()
: project.createdAt || null;
if (!startDate) return;
const timeToEvent = millisecondsToSeconds(
new Date().getTime() - project.createdAt.getTime(),
Date.now() - startDate.getTime(),
);
await this.onboardingStore.insertProjectEvent({
type: event.type,