eletrotupi / tcc/ api/tests/reports/report-data.unit.test.tsc901c35af9c84b6a29e5185545ced1129f33b8f4
4.4 KB | 168 lines Raw
1
import { describe, it, expect } from 'vitest'
2
import {
3
  BaseMoodOption,
4
  MoodComponentOption,
5
  IntensityLevel,
6
} from '@prisma/client'
7
import {
8
  buildMoodDistribution,
9
  buildDailyMoods,
10
  buildTopComponents,
11
  buildCheckinLog,
12
} from '@app/reports/report.data'
13

14
const mood = (selectedMood: BaseMoodOption) => ({ selectedMood })
15

16
// Local-noon instants keep the yyyy-MM-dd grouping stable across timezones
17
const at = (year: number, month: number, day: number, hour = 12) =>
18
  new Date(year, month - 1, day, hour)
19

20
describe('buildMoodDistribution', () => {
21
  it('counts each base mood and computes its share of the period', () => {
22
    const distribution = buildMoodDistribution(
23
      [mood('GREAT'), mood('GREAT'), mood('GOOD')],
24
      3,
25
    )
26

27
    expect(distribution).toEqual([
28
      { mood: 'GREAT', count: 2, pct: 66.7 },
29
      { mood: 'GOOD', count: 1, pct: 33.3 },
30
      { mood: 'NEUTRAL', count: 0, pct: 0 },
31
      { mood: 'SAD', count: 0, pct: 0 },
32
      { mood: 'ANGRY', count: 0, pct: 0 },
33
    ])
34
  })
35

36
  it('reports all zeros for an empty period', () => {
37
    const order: BaseMoodOption[] = [
38
      'GREAT',
39
      'GOOD',
40
      'NEUTRAL',
41
      'SAD',
42
      'ANGRY',
43
    ]
44

45
    expect(buildMoodDistribution([], 0)).toEqual(
46
      order.map(mood => ({ mood, count: 0, pct: 0 })),
47
    )
48
  })
49
})
50

51
describe('buildDailyMoods', () => {
52
  it('keeps the latest Mood Entry of each day, whatever the order', () => {
53
    const daily = buildDailyMoods(
54
      [
55
        { moment: at(2026, 10, 17, 20), selectedMood: 'GREAT' },
56
        { moment: at(2026, 10, 17, 8), selectedMood: 'SAD' },
57
      ],
58
      [at(2026, 10, 17)],
59
    )
60

61
    expect(daily).toEqual([{ date: '2026-10-17', mood: 'GREAT' }])
62
  })
63

64
  it('yields a null mood for a day with no entry', () => {
65
    const daily = buildDailyMoods(
66
      [{ moment: at(2026, 10, 17, 9), selectedMood: 'GOOD' }],
67
      [at(2026, 10, 16), at(2026, 10, 17), at(2026, 10, 18)],
68
    )
69

70
    expect(daily).toEqual([
71
      { date: '2026-10-16', mood: null },
72
      { date: '2026-10-17', mood: 'GOOD' },
73
      { date: '2026-10-18', mood: null },
74
    ])
75
  })
76
})
77

78
describe('buildTopComponents', () => {
79
  it('counts each component and keeps the most frequent intensity', () => {
80
    const components = buildTopComponents([
81
      {
82
        moodComponents: [
83
          { component: 'JOY', intensity: 'LIGHT' },
84
          { component: 'CALM', intensity: 'HIGH' },
85
        ],
86
      },
87
      {
88
        moodComponents: [
89
          { component: 'JOY', intensity: 'LIGHT' },
90
          { component: 'JOY', intensity: 'HIGH' },
91
        ],
92
      },
93
    ])
94

95
    expect(components).toEqual([
96
      { component: 'JOY', count: 3, avgIntensity: 'LIGHT' },
97
      { component: 'CALM', count: 1, avgIntensity: 'HIGH' },
98
    ])
99
  })
100

101
  it('keeps only the ten most frequent components', () => {
102
    const components: MoodComponentOption[] = [
103
      'JOY', 'ANGER', 'SADNESS', 'FEAR', 'GUILT', 'FRUSTRATION',
104
      'CALM', 'MOTIVATED', 'TIREDNESS', 'GRATITUDE', 'FOCUS',
105
    ]
106

107
    const moods = components.flatMap((component, i) =>
108
      Array.from({ length: 11 - i }, () => ({
109
        moodComponents: [{ component, intensity: 'LIGHT' as IntensityLevel }],
110
      })),
111
    )
112

113
    const top = buildTopComponents(moods)
114

115
    expect(top).toHaveLength(10)
116
    expect(top[0]).toEqual({
117
      component: 'JOY',
118
      count: 11,
119
      avgIntensity: 'LIGHT',
120
    })
121
    expect(top.map(c => c.component)).not.toContain('FOCUS')
122
  })
123
})
124

125
describe('buildCheckinLog', () => {
126
  it('projects the log fields and renames the mood', () => {
127
    const moment = at(2026, 10, 17, 8)
128

129
    const log = buildCheckinLog([
130
      {
131
        moment,
132
        selectedMood: 'GOOD',
133
        anxietyLevel: 2,
134
        stressLevel: 3,
135
        energyLevel: 7,
136
        annotation: 'manhã calma',
137
      },
138
    ])
139

140
    expect(log).toEqual([
141
      {
142
        moment,
143
        mood: 'GOOD',
144
        anxietyLevel: 2,
145
        stressLevel: 3,
146
        energyLevel: 7,
147
        annotation: 'manhã calma',
148
      },
149
    ])
150
  })
151

152
  it('keeps at most the fifty most recent entries', () => {
153
    const entry = (i: number) => ({
154
      moment: at(2026, 10, 1, 0),
155
      selectedMood: 'GOOD' as BaseMoodOption,
156
      anxietyLevel: 1,
157
      stressLevel: 1,
158
      energyLevel: 1,
159
      annotation: `n${i}`,
160
    })
161

162
    const log = buildCheckinLog(Array.from({ length: 51 }, (_, i) => entry(i)))
163

164
    expect(log).toHaveLength(50)
165
    expect(log[0].annotation).toBe('n0')
166
    expect(log[49].annotation).toBe('n49')
167
  })
168
})