eletrotupi / tcc/ api/tests/jobs/push-notifications.test.ts30f98b88ba3e0926a1a93ed3c7a9e2618d9ff920
5.1 KB | 175 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
        }),
70
      })
71
    )
72
  })
73

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

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

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

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

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

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

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

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

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

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

157
    await dailyReminderProcessor({
158
      data: { userId: user.id, scheduledTime: '20:00' },
159
    } as any)
160

161
    expect(mockedSend).not.toHaveBeenCalled()
162
    const row = await db.notification.findFirst()
163
    expect(row?.kind).toBe('DAILY_REMINDER')
164
    expect(row?.pushedAt).toBeNull()
165
  })
166

167
  it('stores nothing when the user does not exist', async () => {
168
    await dailyReminderProcessor({
169
      data: { userId: 999999, scheduledTime: '20:00' },
170
    } as any)
171

172
    expect(mockedSend).not.toHaveBeenCalled()
173
    expect(await db.notification.count()).toBe(0)
174
  })
175
})