From a2ca7b0d35b5e559c4ff3db20e107dccd4d04bd2 Mon Sep 17 00:00:00 2001
From: Fredrik Strand Oseberg <fredrik.no@gmail.com>
Date: Tue, 10 Oct 2023 14:40:36 +0200
Subject: [PATCH] Refactor/last seen at read feature overview (#4986)

Refactor feature overview to use the last seen store
---
 src/lib/db/feature-strategy-store.ts          | 15 ++++++
 .../api/admin/project/projects.e2e.test.ts    | 46 +++++++++++-----
 .../feature-toggle-service-v2.e2e.test.ts     | 54 +++++++++++++++++++
 3 files changed, 103 insertions(+), 12 deletions(-)

diff --git a/src/lib/db/feature-strategy-store.ts b/src/lib/db/feature-strategy-store.ts
index 8266dfab18..a5584c215e 100644
--- a/src/lib/db/feature-strategy-store.ts
+++ b/src/lib/db/feature-strategy-store.ts
@@ -339,6 +339,19 @@ class FeatureStrategiesStore implements IFeatureStrategiesStore {
             .modify(FeatureToggleStore.filterByArchived, archived);
 
         let selectColumns = ['features_view.*'] as (string | Raw<any>)[];
+
+        if (this.flagResolver.isEnabled('useLastSeenRefactor')) {
+            query.leftJoin(
+                'last_seen_at_metrics',
+                'last_seen_at_metrics.environment',
+                'features_view.environment_name',
+            );
+            // Override feature view for now
+            selectColumns.push(
+                'last_seen_at_metrics.last_seen_at as env_last_seen_at',
+            );
+        }
+
         if (userId) {
             query = query.leftJoin(`favorite_features`, function () {
                 this.on(
@@ -353,8 +366,10 @@ class FeatureStrategiesStore implements IFeatureStrategiesStore {
                 ),
             ];
         }
+
         const rows = await query.select(selectColumns);
         stopTimer();
+
         if (rows.length > 0) {
             const featureToggle = rows.reduce((acc, r) => {
                 if (acc.environments === undefined) {
diff --git a/src/test/e2e/api/admin/project/projects.e2e.test.ts b/src/test/e2e/api/admin/project/projects.e2e.test.ts
index 012496a4f7..4830f3191c 100644
--- a/src/test/e2e/api/admin/project/projects.e2e.test.ts
+++ b/src/test/e2e/api/admin/project/projects.e2e.test.ts
@@ -6,32 +6,38 @@ import {
 import getLogger from '../../../../fixtures/no-logger';
 
 import { IProjectStore } from 'lib/types';
-import { ProjectService } from 'lib/services';
+import { Knex } from 'knex';
 
 let app: IUnleashTest;
 let db: ITestDb;
 
 let projectStore: IProjectStore;
 
-const insertLastSeenAt = async (
+export const insertLastSeenAt = async (
     featureName: string,
+    db: Knex,
     environment: string = 'default',
     date: string = '2023-10-01 12:34:56',
-) => {
-    await db.rawDatabase.raw(`INSERT INTO last_seen_at_metrics (feature_name, environment, last_seen_at)
+): Promise<string> => {
+    await db.raw(`INSERT INTO last_seen_at_metrics (feature_name, environment, last_seen_at)
         VALUES ('${featureName}', '${environment}', '${date}');`);
+
+    return date;
 };
 
-const insertFeatureEnvironmentsLastSeen = async (
+export const insertFeatureEnvironmentsLastSeen = async (
     featureName: string,
+    db: Knex,
     environment: string = 'default',
     date: string = '2022-05-01 12:34:56',
-) => {
-    await db.rawDatabase.raw(`
+): Promise<string> => {
+    await db.raw(`
         INSERT INTO feature_environments (feature_name, environment, last_seen_at, enabled)
         VALUES ('${featureName}', '${environment}', '${date}', true)
         ON CONFLICT (feature_name, environment) DO UPDATE SET last_seen_at = '${date}', enabled = true;
     `);
+
+    return date;
 };
 
 beforeAll(async () => {
@@ -91,8 +97,12 @@ test('response for default project should include created_at', async () => {
 test('response should include last seen at per environment', async () => {
     await app.createFeature('my-new-feature-toggle');
 
-    await insertLastSeenAt('my-new-feature-toggle', 'default');
-    await insertFeatureEnvironmentsLastSeen('my-new-feature-toggle', 'default');
+    await insertLastSeenAt('my-new-feature-toggle', db.rawDatabase, 'default');
+    await insertFeatureEnvironmentsLastSeen(
+        'my-new-feature-toggle',
+        db.rawDatabase,
+        'default',
+    );
 
     const { body } = await app.request
         .get('/api/admin/projects/default')
@@ -165,9 +175,21 @@ test('response should include last seen at per environment for multiple environm
         'multiple-environment-last-seen-at',
     );
 
-    await insertLastSeenAt('multiple-environment-last-seen-at', 'default');
-    await insertLastSeenAt('multiple-environment-last-seen-at', 'development');
-    await insertLastSeenAt('multiple-environment-last-seen-at', 'production');
+    await insertLastSeenAt(
+        'multiple-environment-last-seen-at',
+        db.rawDatabase,
+        'default',
+    );
+    await insertLastSeenAt(
+        'multiple-environment-last-seen-at',
+        db.rawDatabase,
+        'development',
+    );
+    await insertLastSeenAt(
+        'multiple-environment-last-seen-at',
+        db.rawDatabase,
+        'production',
+    );
 
     const { body } = await appWithLastSeenRefactor.request
         .get('/api/admin/projects/default')
diff --git a/src/test/e2e/services/feature-toggle-service-v2.e2e.test.ts b/src/test/e2e/services/feature-toggle-service-v2.e2e.test.ts
index 624675a705..c9b04d50be 100644
--- a/src/test/e2e/services/feature-toggle-service-v2.e2e.test.ts
+++ b/src/test/e2e/services/feature-toggle-service-v2.e2e.test.ts
@@ -21,6 +21,10 @@ import {
     createFeatureToggleService,
     createSegmentService,
 } from '../../../lib/features';
+import {
+    insertFeatureEnvironmentsLastSeen,
+    insertLastSeenAt,
+} from '../api/admin/project/projects.e2e.test';
 
 let stores: IUnleashStores;
 let db;
@@ -649,3 +653,53 @@ describe('flag name validation', () => {
         }
     });
 });
+
+test('Should return last seen at per environment', async () => {
+    const featureName = 'last-seen-at-per-env';
+    const projectId = 'default';
+
+    const userName = 'last-seen-user';
+
+    await service.createFeatureToggle(
+        projectId,
+        {
+            name: featureName,
+        },
+        userName,
+    );
+
+    const date = await insertFeatureEnvironmentsLastSeen(
+        featureName,
+        db.rawDatabase,
+    );
+
+    const { environments } = await service.getFeature({
+        featureName,
+        projectId: 'default',
+        environmentVariants: false,
+    });
+
+    expect(environments[0].lastSeenAt).toEqual(new Date(date));
+
+    // Test with feature flag on
+    const config = createTestConfig({
+        experimental: { flags: { useLastSeenRefactor: true } },
+    });
+
+    const featureService = createFeatureToggleService(db.rawDatabase, config);
+
+    const lastSeenAtStoreDate = await insertLastSeenAt(
+        featureName,
+        db.rawDatabase,
+    );
+
+    const featureToggle = await featureService.getFeature({
+        featureName,
+        projectId: 'default',
+        environmentVariants: false,
+    });
+
+    expect(featureToggle.environments[0].lastSeenAt).toEqual(
+        new Date(lastSeenAtStoreDate),
+    );
+});