Skip to content

Commit ab84df2

Browse files
committed
feat: update user app count retrieval to only include moderated apps
1 parent e13d706 commit ab84df2

2 files changed

Lines changed: 61 additions & 5 deletions

File tree

backend/src/routes/users.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ export function createUsersRouter(db: Knex, notificationService: INotificationSe
2424
const router = Router()
2525

2626
/**
27-
* Get users with app counts (limited to users with at least one app)
28-
* Returns maximum 200 users sorted by app count in descending order
27+
* Get users with app counts, sorted by number of moderated apps they have created
28+
* Only counts moderated apps (approved apps) for ranking
29+
* Returns maximum 200 users sorted by moderated app count in descending order
2930
*/
3031
router.get('/with-app-counts', async (req, res) => {
3132
try {
@@ -45,6 +46,7 @@ export function createUsersRouter(db: Knex, notificationService: INotificationSe
4546
.select('users.address', 'users.win_1_amount')
4647
.count('apps.id as app_count')
4748
.join('apps', 'users.address', 'apps.owner_address')
49+
.where('apps.moderated', true) // Only count moderated apps
4850
.groupBy('users.address', 'users.win_1_amount')
4951
.having(db.raw('count(apps.id) >= 1'))
5052
.orderBy('users.win_1_amount', 'desc')
@@ -68,6 +70,7 @@ export function createUsersRouter(db: Knex, notificationService: INotificationSe
6870
.select('users.address', 'users.win_1_amount')
6971
.count('apps.id as app_count')
7072
.join('apps', 'users.address', 'apps.owner_address')
73+
.where('apps.moderated', true) // Only count moderated apps for ranking too
7174
.groupBy('users.address', 'users.win_1_amount')
7275
.having(db.raw('count(apps.id) >= 1'))
7376
.orderBy('users.win_1_amount', 'desc')
@@ -143,6 +146,7 @@ export function createUsersRouter(db: Knex, notificationService: INotificationSe
143146
.select('users.address', 'users.win_1_amount')
144147
.count('apps.id as app_count')
145148
.join('apps', 'users.address', 'apps.owner_address')
149+
.where('apps.moderated', true) // Only count moderated apps
146150
.whereNotNull('users.win_1_amount')
147151
.where('users.win_1_amount', '>', '0') // Only get users with positive win amount
148152
.groupBy('users.address', 'users.win_1_amount')

backend/src/tests/users.test.ts

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -330,10 +330,10 @@ describe('Users API', () => {
330330
owner_address: address,
331331
})
332332

333-
// Create some test apps for the user
333+
// Create some test apps for the user (must be moderated to be counted)
334334
await db('apps').insert([
335-
{ name: 'Test App 1', owner_address: address, template_id: templateId },
336-
{ name: 'Test App 2', owner_address: address, template_id: templateId },
335+
{ name: 'Test App 1', owner_address: address, template_id: templateId, moderated: true },
336+
{ name: 'Test App 2', owner_address: address, template_id: templateId, moderated: true },
337337
])
338338

339339
const response = await request(app).get('/api/with-app-counts')
@@ -359,6 +359,58 @@ describe('Users API', () => {
359359
expect(Number(testUser?.app_count)).toBe(2) // Count is returned as string from the database
360360
})
361361

362+
it('should only count moderated apps, not non-moderated apps', async () => {
363+
// Create test users
364+
const address1 = '0x1234567890123456789012345678901234567890'
365+
const address2 = '0x2345678901234567890123456789012345678901'
366+
await db('users').insert([{ address: address1 }, { address: address2 }])
367+
368+
// Create a test template
369+
const [templateId] = await db('templates').insert({
370+
title: 'Test Template',
371+
url: 'https://example.com',
372+
json_data: '{}',
373+
owner_address: address1,
374+
})
375+
376+
// User 1: 2 moderated apps, 1 non-moderated app
377+
await db('apps').insert([
378+
{ name: 'Moderated App 1', owner_address: address1, template_id: templateId, moderated: true },
379+
{ name: 'Moderated App 2', owner_address: address1, template_id: templateId, moderated: true },
380+
{ name: 'Non-moderated App', owner_address: address1, template_id: templateId, moderated: false },
381+
])
382+
383+
// User 2: Only non-moderated apps (should not appear in results)
384+
await db('apps').insert([
385+
{ name: 'Non-moderated App 3', owner_address: address2, template_id: templateId, moderated: false },
386+
{ name: 'Non-moderated App 4', owner_address: address2, template_id: templateId, moderated: false },
387+
])
388+
389+
const response = await request(app).get('/api/with-app-counts')
390+
391+
expect(response.status).toBe(200)
392+
expect(response.body).toHaveProperty('users')
393+
394+
// Type the response body properly
395+
interface UserResponse {
396+
trimmed_address: string
397+
app_count: string
398+
}
399+
400+
const responseBody = response.body.users as UserResponse[]
401+
402+
// User 1 should appear with count of 2 (only moderated apps)
403+
const expectedTrimmedAddress1 = `${address1.substring(0, 7)}...${address1.substring(address1.length - 5)}`
404+
const testUser1 = responseBody.find(user => user.trimmed_address === expectedTrimmedAddress1)
405+
expect(testUser1).toBeDefined()
406+
expect(Number(testUser1?.app_count)).toBe(2) // Only moderated apps counted
407+
408+
// User 2 should NOT appear because they have no moderated apps
409+
const expectedTrimmedAddress2 = `${address2.substring(0, 7)}...${address2.substring(address2.length - 5)}`
410+
const testUser2 = responseBody.find(user => user.trimmed_address === expectedTrimmedAddress2)
411+
expect(testUser2).toBeUndefined()
412+
})
413+
362414
it('should handle database errors gracefully', async () => {
363415
// Silence console.error during this test
364416
console.error = jest.fn()

0 commit comments

Comments
 (0)