eletrotupi / tcc/ api/tests/jobs/push-notifications.test.tsf6425d4096f950efeafb0cfb4405841fd35f2f8e
5.2 KB | 179 lines Raw
1
import { describe, it, expect, afterAll, beforeEach, vi } from 'vitest'
2
import { medicineReminderProcessor } from '@app/lib/queue/processors/medicineReminders'
3
import { dailyReminderProcessor } from '@app/lib/queue/processors/dailyReminders'
4
import { buildPrisma, cleanupTestDb, createTestUser } from '../test-helper'
5

6
// Prevent any Expo push API calls
7
vi.mock('@app/lib/sendPushNotification', () => ({
8
  sendPushNotification: vi.fn().mockResolvedValue(undefined),
9
}))
10

11
import { sendPushNotification } from '@app/lib/sendPushNotification'
12
const mockedSend = vi.mocked(sendPushNotification)
13

14
const db = buildPrisma()
15

16
afterAll(() => db.$disconnect())
17
beforeEach(async () => {
18
  await cleanupTestDb(db)
19
  mockedSend.mockClear()
20
})
21

22
describe('medicineReminderProcessor', () => {
23
  it('stores a medicine notification for the dose time and pushes it', async () => {
24
    const user = await createTestUser(db, {
25
      pushToken: 'ExponentPushToken[abc123]',
26
    })
27
    const regimen = await db.medicineRegimen.create({
28
      data: {
29
        name: 'Sertralina',
30
        dosage: '50mg',
31
        periodicity: 'DAILY',
32
        scheduledAt: ['08:00'],
33
        userId: user.id,
34
      },
35
    })
36

37
    await medicineReminderProcessor({
38
      data: {
39
        userId: user.id,
40
        regimenId: regimen.id,
41
        medicineName: 'Sertralina',
42
        dosage: '50mg',
43
        scheduledTime: '08:00',
44
      },
45
    } as any)
46

47
    const row = await db.notification.findFirst()
48
    expect(row).toMatchObject({
49
      userId: user.id,
50
      kind: 'MEDICINE_REMINDER',
51
      title: 'Hora de tomar Sertralina',
52
      body: '50mg',
53
      regimenId: regimen.id,
54
    })
55
    // 08:00 in São Paulo (UTC-3)
56
    expect(row?.scheduledFor.getUTCHours()).toBe(11)
57
    expect(row?.scheduledFor.getUTCMinutes()).toBe(0)
58
    expect(row?.pushedAt).not.toBeNull()
59

60
    expect(mockedSend).toHaveBeenCalledOnce()
61
    expect(mockedSend).toHaveBeenCalledWith(
62
      expect.objectContaining({
63
        token: 'ExponentPushToken[abc123]',
64
        title: 'Hora de tomar Sertralina',
65
        body: '50mg',
66
        data: expect.objectContaining({
67
          screen: 'medicine-regimens',
68
          regimenId: regimen.id,
69
          notificationId: row!.id,
70
        }),
71
      })
72
    )
73
  })
74

75
  it('stores the notification without pushing when the user has no token', async () => {
76
    const user = await createTestUser(db) // no pushToken
77
    const regimen = await db.medicineRegimen.create({
78
      data: {
79
        name: 'Ritalina',
80
        dosage: '10mg',
81
        periodicity: 'DAILY',
82
        scheduledAt: ['12:00'],
83
        userId: user.id,
84
      },
85
    })
86

87
    await medicineReminderProcessor({
88
      data: {
89
        userId: user.id,
90
        regimenId: regimen.id,
91
        medicineName: 'Ritalina',
92
        dosage: '10mg',
93
        scheduledTime: '12:00',
94
      },
95
    } as any)
96

97
    expect(mockedSend).not.toHaveBeenCalled()
98
    const row = await db.notification.findFirst()
99
    expect(row?.kind).toBe('MEDICINE_REMINDER')
100
    expect(row?.pushedAt).toBeNull()
101
  })
102

103
  it('stores nothing when the user does not exist', async () => {
104
    await medicineReminderProcessor({
105
      data: {
106
        userId: 999999,
107
        regimenId: 1,
108
        medicineName: 'X',
109
        dosage: 'Y',
110
        scheduledTime: '08:00',
111
      },
112
    } as any)
113

114
    expect(mockedSend).not.toHaveBeenCalled()
115
    expect(await db.notification.count()).toBe(0)
116
  })
117
})
118

119
describe('dailyReminderProcessor', () => {
120
  it('stores a daily notification for the reminder time and pushes it', async () => {
121
    const user = await createTestUser(db, {
122
      pushToken: 'ExponentPushToken[daily123]',
123
      pushEnabled: true,
124
    })
125

126
    await dailyReminderProcessor({
127
      data: { userId: user.id, scheduledTime: '20:00' },
128
    } as any)
129

130
    const row = await db.notification.findFirst()
131
    expect(row).toMatchObject({
132
      userId: user.id,
133
      kind: 'DAILY_REMINDER',
134
      title: 'Como você está?',
135
      body: 'Registre seu humor para acompanhar sua saúde.',
136
    })
137
    // 20:00 in São Paulo (UTC-3)
138
    expect(row?.scheduledFor.getUTCHours()).toBe(23)
139
    expect(row?.scheduledFor.getUTCMinutes()).toBe(0)
140
    expect(row?.pushedAt).not.toBeNull()
141

142
    expect(mockedSend).toHaveBeenCalledOnce()
143
    expect(mockedSend).toHaveBeenCalledWith(
144
      expect.objectContaining({
145
        token: 'ExponentPushToken[daily123]',
146
        title: 'Como você está?',
147
        data: expect.objectContaining({
148
          screen: 'moods',
149
          notificationId: row!.id,
150
        }),
151
      })
152
    )
153
  })
154

155
  it('stores the notification without pushing when notifications are disabled', async () => {
156
    const user = await createTestUser(db, {
157
      pushToken: 'ExponentPushToken[disabled]',
158
      pushEnabled: false,
159
    })
160

161
    await dailyReminderProcessor({
162
      data: { userId: user.id, scheduledTime: '20:00' },
163
    } as any)
164

165
    expect(mockedSend).not.toHaveBeenCalled()
166
    const row = await db.notification.findFirst()
167
    expect(row?.kind).toBe('DAILY_REMINDER')
168
    expect(row?.pushedAt).toBeNull()
169
  })
170

171
  it('stores nothing when the user does not exist', async () => {
172
    await dailyReminderProcessor({
173
      data: { userId: 999999, scheduledTime: '20:00' },
174
    } as any)
175

176
    expect(mockedSend).not.toHaveBeenCalled()
177
    expect(await db.notification.count()).toBe(0)
178
  })
179
})