From f4268347da69ebd9caa0d9ae19901a079dc78707 Mon Sep 17 00:00:00 2001 From: Jaanus Sellin Date: Mon, 18 Dec 2023 10:36:50 +0200 Subject: [PATCH] fix: last seen now sorts nulls last (#5664) Two changes were needed to sort better 1. Since we are still using `last seen` from `features` table for backwards compatibility, we needed to add it to sort condition. 2. Nulls break the order, so now sorting nulls as last. --- .../feature-search/feature-search-store.ts | 7 ++++++- .../feature-search/feature.search.e2e.test.ts | 19 ++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/lib/features/feature-search/feature-search-store.ts b/src/lib/features/feature-search/feature-search-store.ts index 1973c8f698..a89803bfb6 100644 --- a/src/lib/features/feature-search/feature-search-store.ts +++ b/src/lib/features/feature-search/feature-search-store.ts @@ -227,7 +227,6 @@ class FeatureSearchStore implements IFeatureSearchStore { const sortByMapping = { name: 'features.name', type: 'features.type', - lastSeenAt: lastSeenQuery, stale: 'features.stale', }; @@ -245,6 +244,12 @@ class FeatureSearchStore implements IFeatureSearchStore { [envName], ) .toString(); + } else if (sortBy === 'lastSeenAt') { + rankingSql += `${this.db + .raw( + `coalesce(${lastSeenQuery}, features.last_seen_at) ${validatedSortOrder} nulls last`, + ) + .toString()}, features.created_at asc, features.name asc`; } else if (sortByMapping[sortBy]) { rankingSql += `${this.db .raw(`?? ${validatedSortOrder}`, [ diff --git a/src/lib/features/feature-search/feature.search.e2e.test.ts b/src/lib/features/feature-search/feature.search.e2e.test.ts index de72f3b96c..4fa9d619f6 100644 --- a/src/lib/features/feature-search/feature.search.e2e.test.ts +++ b/src/lib/features/feature-search/feature.search.e2e.test.ts @@ -1,5 +1,6 @@ import dbInit, { ITestDb } from '../../../test/e2e/helpers/database-init'; import { + insertLastSeenAt, IUnleashTest, setupAppWithAuth, } from '../../../test/e2e/helpers/test-helper'; @@ -392,6 +393,8 @@ test('should sort features', async () => { await app.enableFeature('my_feature_c', 'default'); await app.favoriteFeature('my_feature_b'); + await insertLastSeenAt('my_feature_c', db.rawDatabase, 'default'); + const { body: ascName } = await sortFeatures({ sortBy: 'name', sortOrder: 'asc', @@ -476,6 +479,20 @@ test('should sort features', async () => { ], total: 3, }); + + const { body: lastSeenAscSort } = await sortFeatures({ + sortBy: 'lastSeenAt', + sortOrder: 'asc', + }); + + expect(lastSeenAscSort).toMatchObject({ + features: [ + { name: 'my_feature_c' }, + { name: 'my_feature_a' }, + { name: 'my_feature_b' }, + ], + total: 3, + }); }); test('should sort features when feature names are numbers', async () => { @@ -541,7 +558,7 @@ test('should paginate correctly when using tags', async () => { }); }); -test('should not return duplicate entries when sorting by last seen', async () => { +test('should not return duplicate entries when sorting by environments', async () => { await app.createFeature('my_feature_a'); await app.createFeature('my_feature_b'); await app.createFeature('my_feature_c');