api: flesh trigger's crud specs
Pedro Lucas Porcellis porcellis@eletrotupi.com · 4 months ago
3213901cb6f40e18df4c191a91f7a34b28de7a6d Browse filesParents
1af3a23Changed files
1
Additions
+238
Deletions
0
/dev/null → api/tests/triggers/crud.test.ts
1 +
import { describe, it, expect, afterAll, beforeEach } from 'vitest'
2 +
import request from 'supertest'
3 +
import { createApp } from '@app/createApp'
4 +
import { buildPrisma, cleanupTestDb, createTestUser, generateTestToken } from '../test-helper'
5 +
6 +
const app = createApp()
7 +
const db = buildPrisma()
8 +
9 +
const moment = new Date().toISOString()
10 +
11 +
afterAll(() => db.$disconnect())
12 +
beforeEach(() => cleanupTestDb(db))
13 +
14 +
async function seedTrigger(
15 +
userId: number,
16 +
overrides: { category?: string; comment?: string } = {}
17 +
) {
18 +
return db.trigger.create({
19 +
data: {
20 +
userId,
21 +
moment: new Date(),
22 +
category: (overrides.category ?? 'WORK') as any,
23 +
comment: overrides.comment,
24 +
},
25 +
})
26 +
}
27 +
28 +
describe('POST /triggers', () => {
29 +
it('creates a trigger and returns it', async () => {
30 +
const user = await createTestUser(db)
31 +
const token = generateTestToken(user.id, user.email)
32 +
33 +
const res = await request(app)
34 +
.post('/triggers')
35 +
.set('Authorization', `Bearer ${token}`)
36 +
.send({
37 +
trigger: {
38 +
moment,
39 +
category: 'SOCIAL',
40 +
comment: 'Reunião difícil',
41 +
},
42 +
})
43 +
44 +
expect(res.status).toBe(201)
45 +
expect(res.body.trigger.category).toBe('SOCIAL')
46 +
expect(res.body.trigger.comment).toBe('Reunião difícil')
47 +
48 +
const dbRecord = await db.trigger.findFirst({ where: { userId: user.id } })
49 +
50 +
expect(dbRecord).not.toBeNull()
51 +
})
52 +
53 +
it('returns 400 for missing required fields', async () => {
54 +
const user = await createTestUser(db)
55 +
const token = generateTestToken(user.id, user.email)
56 +
57 +
const res = await request(app)
58 +
.post('/triggers')
59 +
.set('Authorization', `Bearer ${token}`)
60 +
.send({ trigger: { comment: 'No category or moment' } })
61 +
62 +
expect(res.status).toBe(400)
63 +
})
64 +
65 +
it('returns 401 without a token', async () => {
66 +
const res = await request(app)
67 +
.post('/triggers')
68 +
.send({ trigger: { moment, category: 'WORK' } })
69 +
70 +
expect(res.status).toBe(401)
71 +
})
72 +
})
73 +
74 +
describe('GET /triggers', () => {
75 +
it('returns only the authenticated user\'s triggers', async () => {
76 +
const user = await createTestUser(db)
77 +
const other = await createTestUser(db, { email: 'other@example.com' })
78 +
const token = generateTestToken(user.id, user.email)
79 +
80 +
await seedTrigger(user.id, { category: 'WORK' })
81 +
await seedTrigger(user.id, { category: 'FAMILY' })
82 +
await seedTrigger(other.id, { category: 'HEALTH' })
83 +
84 +
const res = await request(app)
85 +
.get('/triggers')
86 +
.set('Authorization', `Bearer ${token}`)
87 +
88 +
expect(res.status).toBe(200)
89 +
expect(res.body.entries).toHaveLength(2)
90 +
expect(res.body.entries.every((t: any) => t.userId === user.id)).toBe(true)
91 +
})
92 +
93 +
it('returns an empty list when no triggers exist', async () => {
94 +
const user = await createTestUser(db)
95 +
const token = generateTestToken(user.id, user.email)
96 +
97 +
const res = await request(app)
98 +
.get('/triggers')
99 +
.set('Authorization', `Bearer ${token}`)
100 +
101 +
expect(res.status).toBe(200)
102 +
expect(res.body.entries).toEqual([])
103 +
expect(res.body.total).toBe(0)
104 +
})
105 +
})
106 +
107 +
describe('GET /triggers/:id', () => {
108 +
it('returns a single trigger', async () => {
109 +
const user = await createTestUser(db)
110 +
const token = generateTestToken(user.id, user.email)
111 +
const trigger = await seedTrigger(user.id, {
112 +
category: 'INTERNAL', comment: 'Anxious'
113 +
})
114 +
115 +
const res = await request(app)
116 +
.get(`/triggers/${trigger.id}`)
117 +
.set('Authorization', `Bearer ${token}`)
118 +
119 +
expect(res.status).toBe(200)
120 +
expect(res.body.id).toBe(trigger.id)
121 +
expect(res.body.category).toBe('INTERNAL')
122 +
expect(res.body.comment).toBe('Anxious')
123 +
})
124 +
})
125 +
126 +
describe('PUT /triggers/:id', () => {
127 +
it('updates trigger fields', async () => {
128 +
const user = await createTestUser(db)
129 +
const token = generateTestToken(user.id, user.email)
130 +
const trigger = await seedTrigger(user.id, { category: 'WORK' })
131 +
132 +
const res = await request(app)
133 +
.put(`/triggers/${trigger.id}`)
134 +
.set('Authorization', `Bearer ${token}`)
135 +
.send({ trigger: { category: 'FAMILY', comment: 'Updated' } })
136 +
137 +
expect(res.status).toBe(200)
138 +
expect(res.body.trigger.category).toBe('FAMILY')
139 +
expect(res.body.trigger.comment).toBe('Updated')
140 +
})
141 +
})
142 +
143 +
describe('DELETE /triggers/:id', () => {
144 +
it('deletes a trigger', async () => {
145 +
const user = await createTestUser(db)
146 +
const token = generateTestToken(user.id, user.email)
147 +
const trigger = await seedTrigger(user.id)
148 +
149 +
const res = await request(app)
150 +
.delete(`/triggers/${trigger.id}`)
151 +
.set('Authorization', `Bearer ${token}`)
152 +
153 +
expect(res.status).toBe(200)
154 +
155 +
const dbRecord = await db.trigger.findUnique({ where: { id: trigger.id } })
156 +
157 +
expect(dbRecord).toBeNull()
158 +
})
159 +
})
160 +
161 +
describe('POST /triggers/:triggerId/link-mood', () => {
162 +
it('links a trigger to a mood', async () => {
163 +
const user = await createTestUser(db)
164 +
const token = generateTestToken(user.id, user.email)
165 +
const trigger = await seedTrigger(user.id)
166 +
167 +
const mood = await db.mood.create({
168 +
data: {
169 +
userId: user.id,
170 +
selectedMood: 'SAD',
171 +
anxietyLevel: 4,
172 +
stressLevel: 4,
173 +
energyLevel: 2,
174 +
moment: new Date(),
175 +
moodComponents: { create: [{ component: 'FEAR', intensity: 'HIGH' }] },
176 +
},
177 +
})
178 +
179 +
const res = await request(app)
180 +
.post(`/triggers/${trigger.id}/link-mood`)
181 +
.set('Authorization', `Bearer ${token}`)
182 +
.send({ moodId: mood.id, perceivedImpact: 3 })
183 +
184 +
expect(res.status).toBe(201)
185 +
expect(res.body.link.triggerId).toBe(trigger.id)
186 +
expect(res.body.link.moodId).toBe(mood.id)
187 +
expect(res.body.link.perceivedImpact).toBe(3)
188 +
})
189 +
190 +
it('returns 400 for invalid perceivedImpact', async () => {
191 +
const user = await createTestUser(db)
192 +
const token = generateTestToken(user.id, user.email)
193 +
const trigger = await seedTrigger(user.id)
194 +
195 +
const res = await request(app)
196 +
.post(`/triggers/${trigger.id}/link-mood`)
197 +
.set('Authorization', `Bearer ${token}`)
198 +
.send({ moodId: 1, perceivedImpact: 10 })
199 +
200 +
expect(res.status).toBe(400)
201 +
})
202 +
})
203 +
204 +
describe('DELETE /triggers/:triggerId/link-mood/:moodId', () => {
205 +
it('unlinks a trigger from a mood', async () => {
206 +
const user = await createTestUser(db)
207 +
const token = generateTestToken(user.id, user.email)
208 +
const trigger = await seedTrigger(user.id)
209 +
210 +
const mood = await db.mood.create({
211 +
data: {
212 +
userId: user.id,
213 +
selectedMood: 'SAD',
214 +
anxietyLevel: 3,
215 +
stressLevel: 3,
216 +
energyLevel: 3,
217 +
moment: new Date(),
218 +
moodComponents: { create: [] },
219 +
},
220 +
})
221 +
222 +
await db.triggerMoodLink.create({
223 +
data: { triggerId: trigger.id, moodId: mood.id, perceivedImpact: 2 },
224 +
})
225 +
226 +
const res = await request(app)
227 +
.delete(`/triggers/${trigger.id}/link-mood/${mood.id}`)
228 +
.set('Authorization', `Bearer ${token}`)
229 +
230 +
expect(res.status).toBe(200)
231 +
232 +
const link = await db.triggerMoodLink.findFirst({
233 +
where: { triggerId: trigger.id, moodId: mood.id },
234 +
})
235 +
236 +
expect(link).toBeNull()
237 +
})
238 +
})