import { describe, it, expect, afterAll, beforeEach } from 'vitest' import request from 'supertest' import { createApp } from '@app/createApp' import { InsightPeriod, InsightType } from '@prisma/client' import { buildPrisma, cleanupTestDb, createTestUser, generateTestToken, } from '../test-helper' const app = createApp() const db = buildPrisma() afterAll(() => db.$disconnect()) beforeEach(() => cleanupTestDb(db)) let seedCounter = 0 // The schema is unique on (userId, type, periodStart), so give every seeded // row a distinct periodStart unless the test asks for a specific one function uniquePeriodStart() { seedCounter += 1 return new Date(Date.UTC(2026, 0, 1) + seedCounter * 60 * 1000) } async function seedInsight( userId: number, overrides: { type?: InsightType period?: InsightPeriod periodStart?: Date generatedAt?: Date title?: string } = {} ) { seedCounter += 1 return db.insight.create({ data: { userId, type: overrides.type ?? InsightType.MOOD_TREND, period: overrides.period ?? InsightPeriod.WEEKLY, title: overrides.title ?? `Insight ${seedCounter}`, body: 'Generated by the insight worker', periodStart: overrides.periodStart ?? uniquePeriodStart(), periodEnd: new Date(), generatedAt: overrides.generatedAt, }, }) } describe('GET /insights', () => { it('returns only the authenticated user\'s insights, newest first', async () => { const user = await createTestUser(db) const other = await createTestUser(db, { email: 'other@example.com' }) const token = generateTestToken(user.id, user.email) await seedInsight(user.id, { title: 'oldest', generatedAt: new Date('2026-01-01') }) await seedInsight(user.id, { title: 'newest', generatedAt: new Date('2026-03-01') }) await seedInsight(user.id, { title: 'middle', generatedAt: new Date('2026-02-01') }) await seedInsight(other.id, { title: 'not-mine' }) const res = await request(app) .get('/insights') .set('Authorization', `Bearer ${token}`) expect(res.status).toBe(200) expect(res.body.insights).toHaveLength(3) expect(res.body.insights.every((i: any) => i.userId === user.id)).toBe(true) expect(res.body.insights.map((i: any) => i.title)).toEqual([ 'newest', 'middle', 'oldest', ]) }) it('returns an empty list when the user has no insights', async () => { const user = await createTestUser(db) const token = generateTestToken(user.id, user.email) const res = await request(app) .get('/insights') .set('Authorization', `Bearer ${token}`) expect(res.status).toBe(200) expect(res.body.insights).toEqual([]) }) it('filters by type', async () => { const user = await createTestUser(db) const token = generateTestToken(user.id, user.email) await seedInsight(user.id, { type: InsightType.MOOD_TREND }) await seedInsight(user.id, { type: InsightType.STREAK }) await seedInsight(user.id, { type: InsightType.STREAK }) const res = await request(app) .get('/insights?type=STREAK') .set('Authorization', `Bearer ${token}`) expect(res.status).toBe(200) expect(res.body.insights).toHaveLength(2) expect(res.body.insights.every((i: any) => i.type === 'STREAK')).toBe(true) }) it('filters by period', async () => { const user = await createTestUser(db) const token = generateTestToken(user.id, user.email) await seedInsight(user.id, { period: InsightPeriod.DAILY }) await seedInsight(user.id, { period: InsightPeriod.MONTHLY }) await seedInsight(user.id, { period: InsightPeriod.MONTHLY }) const res = await request(app) .get('/insights?period=MONTHLY') .set('Authorization', `Bearer ${token}`) expect(res.status).toBe(200) expect(res.body.insights).toHaveLength(2) expect(res.body.insights.every((i: any) => i.period === 'MONTHLY')).toBe(true) }) it('caps the result set at the requested limit', async () => { const user = await createTestUser(db) const token = generateTestToken(user.id, user.email) await seedInsight(user.id) await seedInsight(user.id) await seedInsight(user.id) const res = await request(app) .get('/insights?limit=2') .set('Authorization', `Bearer ${token}`) expect(res.status).toBe(200) expect(res.body.insights).toHaveLength(2) }) it('returns 400 for an unknown type', async () => { const user = await createTestUser(db) const token = generateTestToken(user.id, user.email) const res = await request(app) .get('/insights?type=NOPE') .set('Authorization', `Bearer ${token}`) expect(res.status).toBe(400) expect(res.body.fields).toBeTruthy() }) it('returns 400 for a non-positive limit', async () => { const user = await createTestUser(db) const token = generateTestToken(user.id, user.email) const res = await request(app) .get('/insights?limit=0') .set('Authorization', `Bearer ${token}`) expect(res.status).toBe(400) }) it('returns 401 without a token', async () => { const res = await request(app).get('/insights') expect(res.status).toBe(401) }) })