| 1 | import { describe, it, expect, afterAll, beforeEach } from 'vitest'
|
| 2 | import { processMoodTrend } from '@app/lib/queue/processors/insights/moodTrend'
|
| 3 | import { buildPrisma, cleanupTestDb, createTestUser } from '../test-helper'
|
| 4 |
|
| 5 | const db = buildPrisma()
|
| 6 |
|
| 7 | afterAll(() => db.$disconnect())
|
| 8 | beforeEach(() => cleanupTestDb(db))
|
| 9 |
|
| 10 | describe('processMoodTrend', () => {
|
| 11 | it('skips processing when fewer than 3 mood entries exist', async () => {
|
| 12 | const user = await createTestUser(db)
|
| 13 | const now = new Date()
|
| 14 | const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000)
|
| 15 |
|
| 16 | await db.mood.create({
|
| 17 | data: {
|
| 18 | userId: user.id,
|
| 19 | selectedMood: 'GOOD',
|
| 20 | anxietyLevel: 2,
|
| 21 | stressLevel: 2,
|
| 22 | energyLevel: 7,
|
| 23 | moment: new Date(weekAgo.getTime() + 60_000),
|
| 24 | moodComponents: { create: [{ component: 'JOY', intensity: 'LIGHT' }] },
|
| 25 | },
|
| 26 | })
|
| 27 |
|
| 28 | await processMoodTrend({
|
| 29 | userId: user.id,
|
| 30 | periodStart: weekAgo.toISOString(),
|
| 31 | periodEnd: now.toISOString(),
|
| 32 | })
|
| 33 |
|
| 34 | const insight = await db.insight.findFirst({ where: { userId: user.id } })
|
| 35 | expect(insight).toBeNull()
|
| 36 | })
|
| 37 |
|
| 38 | it('creates a MOOD_TREND insight when enough entries exist', async () => {
|
| 39 | const user = await createTestUser(db)
|
| 40 | const now = new Date()
|
| 41 | const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000)
|
| 42 |
|
| 43 | const moods = ['GREAT', 'GOOD', 'NEUTRAL', 'GOOD', 'GREAT'] as const
|
| 44 | for (let i = 0; i < moods.length; i++) {
|
| 45 | await db.mood.create({
|
| 46 | data: {
|
| 47 | userId: user.id,
|
| 48 | selectedMood: moods[i],
|
| 49 | anxietyLevel: 2,
|
| 50 | stressLevel: 2,
|
| 51 | energyLevel: 7,
|
| 52 | moment: new Date(weekAgo.getTime() + i * 24 * 60 * 60 * 1000),
|
| 53 | moodComponents: { create: [{ component: 'JOY', intensity: 'LIGHT' }] },
|
| 54 | },
|
| 55 | })
|
| 56 | }
|
| 57 |
|
| 58 | await processMoodTrend({
|
| 59 | userId: user.id,
|
| 60 | periodStart: weekAgo.toISOString(),
|
| 61 | periodEnd: now.toISOString(),
|
| 62 | })
|
| 63 |
|
| 64 | const insight = await db.insight.findFirst({ where: { userId: user.id, type: 'MOOD_TREND' } })
|
| 65 | expect(insight).not.toBeNull()
|
| 66 | expect(insight!.title).toBe('Tendência de Humor')
|
| 67 | expect(insight!.metadata).toMatchObject({
|
| 68 | dominantMood: expect.any(String),
|
| 69 | delta: expect.any(Number),
|
| 70 | })
|
| 71 | })
|
| 72 |
|
| 73 | it('upserts the insight on repeated calls for the same period', async () => {
|
| 74 | const user = await createTestUser(db)
|
| 75 | const now = new Date()
|
| 76 | const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000)
|
| 77 |
|
| 78 | for (let i = 0; i < 4; i++) {
|
| 79 | await db.mood.create({
|
| 80 | data: {
|
| 81 | userId: user.id,
|
| 82 | selectedMood: 'GOOD',
|
| 83 | anxietyLevel: 2,
|
| 84 | stressLevel: 2,
|
| 85 | energyLevel: 6,
|
| 86 | moment: new Date(weekAgo.getTime() + i * 24 * 60 * 60 * 1000),
|
| 87 | moodComponents: { create: [{ component: 'JOY', intensity: 'LIGHT' }] },
|
| 88 | },
|
| 89 | })
|
| 90 | }
|
| 91 |
|
| 92 | const periodStart = weekAgo.toISOString()
|
| 93 | const periodEnd = now.toISOString()
|
| 94 |
|
| 95 | await processMoodTrend({ userId: user.id, periodStart, periodEnd })
|
| 96 | await processMoodTrend({ userId: user.id, periodStart, periodEnd })
|
| 97 |
|
| 98 | const count = await db.insight.count({ where: { userId: user.id, type: 'MOOD_TREND' } })
|
| 99 | expect(count).toBe(1)
|
| 100 | })
|
| 101 | })
|