eletrotupi / tcc/ api/tests/jobs/daily-insights.test.tsde0605fcb0d1980cedfafe4830a7aeaef31de5dc
6.8 KB | 241 lines Raw
1
import { describe, it, expect, afterAll, beforeEach } from 'vitest'
2
import { processDailyEnergy } from '@app/lib/queue/processors/insights/dailyEnergy'
3
import { processDailySleep } from '@app/lib/queue/processors/insights/dailySleep'
4
import { appDayWindow } from '@app/lib/queue/processors/insights/utils'
5
import { buildPrisma, cleanupTestDb, createTestUser } from '../test-helper'
6

7
const db = buildPrisma()
8

9
afterAll(() => db.$disconnect())
10
beforeEach(() => cleanupTestDb(db))
11

12
const HOUR = 60 * 60 * 1000
13

14
function createMood(userId: number, energyLevel: number, moment: Date) {
15
  return db.mood.create({
16
    data: {
17
      userId,
18
      selectedMood: 'GOOD',
19
      anxietyLevel: 2,
20
      stressLevel: 2,
21
      energyLevel,
22
      moment,
23
    },
24
  })
25
}
26

27
describe('processDailyEnergy', () => {
28
  it('averages only the mood entries logged inside today', async () => {
29
    const user = await createTestUser(db)
30
    const ref = new Date()
31
    const { start } = appDayWindow(ref)
32

33
    await createMood(user.id, 8, new Date(start.getTime() + HOUR))
34
    await createMood(user.id, 4, new Date(start.getTime() + 2 * HOUR))
35
    // one hour before the app day begins, so it belongs to yesterday
36
    await createMood(user.id, 10, new Date(start.getTime() - HOUR))
37

38
    await processDailyEnergy({
39
      userId: user.id,
40
      periodStart: ref.toISOString(),
41
      periodEnd: ref.toISOString(),
42
    })
43

44
    const insight = await db.insight.findFirst({
45
      where: { userId: user.id, type: 'DAILY_ENERGY' },
46
    })
47

48
    expect(insight).not.toBeNull()
49
    expect(insight!.periodStart).toEqual(start)
50
    expect(insight!.metadata).toMatchObject({ avgEnergy: 6, entryCount: 2 })
51
  })
52

53
  it('writes nothing when no mood entry falls inside today', async () => {
54
    const user = await createTestUser(db)
55
    const ref = new Date()
56
    const { start } = appDayWindow(ref)
57

58
    await createMood(user.id, 9, new Date(start.getTime() - HOUR))
59

60
    await processDailyEnergy({
61
      userId: user.id,
62
      periodStart: ref.toISOString(),
63
      periodEnd: ref.toISOString(),
64
    })
65

66
    const insight = await db.insight.findFirst({
67
      where: { userId: user.id, type: 'DAILY_ENERGY' },
68
    })
69

70
    expect(insight).toBeNull()
71
  })
72

73
  it('compares today against yesterday and labels the window', async () => {
74
    const user = await createTestUser(db)
75
    const ref = new Date()
76
    const { start } = appDayWindow(ref)
77
    const { start: yesterday } = appDayWindow(new Date(start.getTime() - 1))
78

79
    await createMood(user.id, 8, new Date(start.getTime() + HOUR))
80
    await createMood(user.id, 6, new Date(start.getTime() + 2 * HOUR))
81
    await createMood(user.id, 3, new Date(yesterday.getTime() + HOUR))
82
    await createMood(user.id, 5, new Date(yesterday.getTime() + 2 * HOUR))
83

84
    await processDailyEnergy({
85
      userId: user.id,
86
      periodStart: ref.toISOString(),
87
      periodEnd: ref.toISOString(),
88
    })
89

90
    const insight = await db.insight.findFirst({
91
      where: { userId: user.id, type: 'DAILY_ENERGY' },
92
    })
93

94
    expect(insight).not.toBeNull()
95
    expect(insight!.metadata).toMatchObject({
96
      avgEnergy: 7,
97
      yesterdayAvg: 4,
98
      diffEnergy: 3,
99
      windowLabel: 'hoje',
100
    })
101
  })
102

103
  it('omits the comparison when yesterday has no mood entry', async () => {
104
    const user = await createTestUser(db)
105
    const ref = new Date()
106
    const { start } = appDayWindow(ref)
107

108
    await createMood(user.id, 6, new Date(start.getTime() + HOUR))
109

110
    await processDailyEnergy({
111
      userId: user.id,
112
      periodStart: ref.toISOString(),
113
      periodEnd: ref.toISOString(),
114
    })
115

116
    const insight = await db.insight.findFirst({
117
      where: { userId: user.id, type: 'DAILY_ENERGY' },
118
    })
119

120
    expect(insight).not.toBeNull()
121
    expect(insight!.metadata).toMatchObject({
122
      avgEnergy: 6,
123
      yesterdayAvg: null,
124
      diffEnergy: null,
125
    })
126
  })
127
})
128

129
describe('processDailySleep', () => {
130
  it('sums today and compares against yesterday', async () => {
131
    const user = await createTestUser(db)
132
    const ref = new Date()
133
    const { start: today } = appDayWindow(ref)
134
    const { start: yesterday } = appDayWindow(new Date(today.getTime() - 1))
135

136
    await db.sleepRecord.create({
137
      data: { userId: user.id, date: today, average: 8 },
138
    })
139
    await db.sleepRecord.create({
140
      data: { userId: user.id, date: yesterday, average: 6 },
141
    })
142

143
    await processDailySleep({
144
      userId: user.id,
145
      periodStart: ref.toISOString(),
146
      periodEnd: ref.toISOString(),
147
    })
148

149
    const insight = await db.insight.findFirst({
150
      where: { userId: user.id, type: 'DAILY_SLEEP' },
151
    })
152

153
    expect(insight).not.toBeNull()
154
    expect(insight!.periodStart).toEqual(today)
155
    expect(insight!.metadata).toMatchObject({
156
      totalHours: 8,
157
      diffMinutes: 120,
158
    })
159
  })
160

161
  it('writes nothing when no sleep record falls inside today', async () => {
162
    const user = await createTestUser(db)
163
    const ref = new Date()
164
    const { start: today } = appDayWindow(ref)
165
    const { start: yesterday } = appDayWindow(new Date(today.getTime() - 1))
166

167
    await db.sleepRecord.create({
168
      data: { userId: user.id, date: yesterday, average: 7 },
169
    })
170

171
    await processDailySleep({
172
      userId: user.id,
173
      periodStart: ref.toISOString(),
174
      periodEnd: ref.toISOString(),
175
    })
176

177
    const insight = await db.insight.findFirst({
178
      where: { userId: user.id, type: 'DAILY_SLEEP' },
179
    })
180

181
    expect(insight).toBeNull()
182
  })
183

184
  it('labels the window and names the extra nap sessions', async () => {
185
    const user = await createTestUser(db)
186
    const ref = new Date()
187
    const { start: today } = appDayWindow(ref)
188

189
    await db.sleepRecord.create({
190
      data: { userId: user.id, date: today, average: 5 },
191
    })
192
    await db.sleepRecord.create({
193
      data: { userId: user.id, date: today, average: 2 },
194
    })
195

196
    await processDailySleep({
197
      userId: user.id,
198
      periodStart: ref.toISOString(),
199
      periodEnd: ref.toISOString(),
200
    })
201

202
    const insight = await db.insight.findFirst({
203
      where: { userId: user.id, type: 'DAILY_SLEEP' },
204
    })
205

206
    expect(insight).not.toBeNull()
207
    expect(insight!.metadata).toMatchObject({
208
      totalHours: 7,
209
      sessionCount: 2,
210
      napStr: 'incluindo 1 cochilo',
211
      windowLabel: 'hoje',
212
    })
213
  })
214

215
  it('omits the comparison when yesterday has no sleep record', async () => {
216
    const user = await createTestUser(db)
217
    const ref = new Date()
218
    const { start: today } = appDayWindow(ref)
219

220
    await db.sleepRecord.create({
221
      data: { userId: user.id, date: today, average: 6 },
222
    })
223

224
    await processDailySleep({
225
      userId: user.id,
226
      periodStart: ref.toISOString(),
227
      periodEnd: ref.toISOString(),
228
    })
229

230
    const insight = await db.insight.findFirst({
231
      where: { userId: user.id, type: 'DAILY_SLEEP' },
232
    })
233

234
    expect(insight).not.toBeNull()
235
    expect(insight!.metadata).toMatchObject({
236
      totalHours: 6,
237
      diffMinutes: null,
238
      diffStr: '',
239
    })
240
  })
241
})