api: introduce tests for care actions and medicine regimens
Parents:
d5fb8793 file(s) changed
- api/tests/care-actions/create.test.ts +124 -0
- api/tests/care-actions/list.test.ts +136 -0
- api/tests/medicine-regimens/crud.test.ts +196 -0
api/tests/care-actions/create.test.ts
@@ -0,0 +1,124 @@
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 + describe('POST /care-actions', () => {
15 + it('creates an ACTIVITY care action', async () => {
16 + const user = await createTestUser(db)
17 + const token = generateTestToken(user.id, user.email)
18 +
19 + const res = await request(app)
20 + .post('/care-actions')
21 + .set('Authorization', `Bearer ${token}`)
22 + .send({
23 + careAction: {
24 + type: 'ACTIVITY',
25 + moment,
26 + activity: { type: 'WALK', duration: 30 },
27 + },
28 + })
29 +
30 + expect(res.status).toBe(201)
31 + expect(res.body.careAction.type).toBe('ACTIVITY')
32 + expect(res.body.careAction.activity.type).toBe('WALK')
33 + expect(res.body.careAction.activity.duration).toBe(30)
34 +
35 + const dbRecord = await db.careAction.findFirst({ where: { userId: user.id } })
36 + expect(dbRecord).not.toBeNull()
37 + })
38 +
39 + it('creates an APPOINTMENT care action', async () => {
40 + const user = await createTestUser(db)
41 + const token = generateTestToken(user.id, user.email)
42 +
43 + const res = await request(app)
44 + .post('/care-actions')
45 + .set('Authorization', `Bearer ${token}`)
46 + .send({
47 + careAction: {
48 + type: 'APPOINTMENT',
49 + moment,
50 + appointment: { type: 'ANALYST', duration: 50, note: 'Primeira sessão' },
51 + },
52 + })
53 +
54 + expect(res.status).toBe(201)
55 + expect(res.body.careAction.type).toBe('APPOINTMENT')
56 + expect(res.body.careAction.appointment.type).toBe('ANALYST')
57 + expect(res.body.careAction.appointment.note).toBe('Primeira sessão')
58 + })
59 +
60 + it('creates a MEDICINE care action linked to an existing regimen', async () => {
61 + const user = await createTestUser(db)
62 + const token = generateTestToken(user.id, user.email)
63 +
64 + const regimen = await db.medicineRegimen.create({
65 + data: {
66 + userId: user.id,
67 + name: 'Sertralina',
68 + dosage: '50mg',
69 + periodicity: 'DAILY',
70 + scheduledAt: [],
71 + },
72 + })
73 +
74 + const res = await request(app)
75 + .post('/care-actions')
76 + .set('Authorization', `Bearer ${token}`)
77 + .send({
78 + careAction: {
79 + type: 'MEDICINE',
80 + moment,
81 + regimenId: regimen.id,
82 + },
83 + })
84 +
85 + expect(res.status).toBe(201)
86 + expect(res.body.careAction.type).toBe('MEDICINE')
87 + expect(res.body.careAction.medicineLog.regimen.id).toBe(regimen.id)
88 + })
89 +
90 + it('creates a MEDICINE care action with inline medicine, creating a new regimen', async () => {
91 + const user = await createTestUser(db)
92 + const token = generateTestToken(user.id, user.email)
93 +
94 + const res = await request(app)
95 + .post('/care-actions')
96 + .set('Authorization', `Bearer ${token}`)
97 + .send({
98 + careAction: {
99 + type: 'MEDICINE',
100 + moment,
101 + medicine: {
102 + name: 'Melatonina',
103 + dosage: '5mg',
104 + periodicity: 'DAILY',
105 + scheduledAt: ['22:00'],
106 + },
107 + },
108 + })
109 +
110 + expect(res.status).toBe(201)
111 + expect(res.body.careAction.medicineLog.regimen.name).toBe('Melatonina')
112 +
113 + const regimenCount = await db.medicineRegimen.count({ where: { userId: user.id } })
114 + expect(regimenCount).toBe(1)
115 + })
116 +
117 + it('returns 401 without a token', async () => {
118 + const res = await request(app)
119 + .post('/care-actions')
120 + .send({ careAction: { type: 'ACTIVITY', moment, activity: { type: 'WALK' } } })
121 +
122 + expect(res.status).toBe(401)
123 + })
124 + })
api/tests/care-actions/list.test.ts
@@ -0,0 +1,136 @@
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 + afterAll(() => db.$disconnect())
10 + beforeEach(() => cleanupTestDb(db))
11 +
12 + async function seedActivity(userId: number, overrides: { moment?: Date } = {}) {
13 + return db.careAction.create({
14 + data: {
15 + userId,
16 + type: 'ACTIVITY',
17 + moment: overrides.moment ?? new Date(),
18 + activity: { create: { type: 'WALK' } },
19 + },
20 + })
21 + }
22 +
23 + describe('GET /care-actions', () => {
24 + it('returns an empty list when no actions exist', async () => {
25 + const user = await createTestUser(db)
26 + const token = generateTestToken(user.id, user.email)
27 +
28 + const res = await request(app)
29 + .get('/care-actions')
30 + .set('Authorization', `Bearer ${token}`)
31 +
32 + expect(res.status).toBe(200)
33 + expect(res.body.entries).toEqual([])
34 + expect(res.body.total).toBe(0)
35 + })
36 +
37 + it('returns only the authenticated user\'s actions', async () => {
38 + const user = await createTestUser(db)
39 + const other = await createTestUser(db, { email: 'other@example.com' })
40 + const token = generateTestToken(user.id, user.email)
41 +
42 + await seedActivity(user.id)
43 + await seedActivity(other.id)
44 +
45 + const res = await request(app)
46 + .get('/care-actions')
47 + .set('Authorization', `Bearer ${token}`)
48 +
49 + expect(res.status).toBe(200)
50 + expect(res.body.entries).toHaveLength(1)
51 + expect(res.body.entries[0].userId).toBe(user.id)
52 + })
53 +
54 + it('filters by type', async () => {
55 + const user = await createTestUser(db)
56 + const token = generateTestToken(user.id, user.email)
57 +
58 + await seedActivity(user.id)
59 + await db.careAction.create({
60 + data: {
61 + userId: user.id,
62 + type: 'APPOINTMENT',
63 + moment: new Date(),
64 + appointment: { create: { type: 'GP', duration: 30 } },
65 + },
66 + })
67 +
68 + const res = await request(app)
69 + .get('/care-actions?type=ACTIVITY')
70 + .set('Authorization', `Bearer ${token}`)
71 +
72 + expect(res.status).toBe(200)
73 + expect(res.body.entries).toHaveLength(1)
74 + expect(res.body.entries[0].type).toBe('ACTIVITY')
75 + })
76 + })
77 +
78 + describe('GET /care-actions/:id', () => {
79 + it('returns a single care action', async () => {
80 + const user = await createTestUser(db)
81 + const token = generateTestToken(user.id, user.email)
82 + const action = await seedActivity(user.id)
83 +
84 + const res = await request(app)
85 + .get(`/care-actions/${action.id}`)
86 + .set('Authorization', `Bearer ${token}`)
87 +
88 + expect(res.status).toBe(200)
89 + expect(res.body.id).toBe(action.id)
90 + })
91 + })
92 +
93 + describe('PATCH /care-actions/:id', () => {
94 + it('links a care action to a mood', async () => {
95 + const user = await createTestUser(db)
96 + const token = generateTestToken(user.id, user.email)
97 + const action = await seedActivity(user.id)
98 +
99 + const mood = await db.mood.create({
100 + data: {
101 + userId: user.id,
102 + selectedMood: 'GOOD',
103 + anxietyLevel: 1,
104 + stressLevel: 1,
105 + energyLevel: 8,
106 + moment: new Date(),
107 + moodComponents: { create: [{ component: 'JOY', intensity: 'LIGHT' }] },
108 + },
109 + })
110 +
111 + const res = await request(app)
112 + .patch(`/care-actions/${action.id}`)
113 + .set('Authorization', `Bearer ${token}`)
114 + .send({ careAction: { moodId: mood.id } })
115 +
116 + expect(res.status).toBe(200)
117 + expect(res.body.moodId).toBe(mood.id)
118 + })
119 + })
120 +
121 + describe('DELETE /care-actions/:id', () => {
122 + it('deletes a care action', async () => {
123 + const user = await createTestUser(db)
124 + const token = generateTestToken(user.id, user.email)
125 + const action = await seedActivity(user.id)
126 +
127 + const res = await request(app)
128 + .delete(`/care-actions/${action.id}`)
129 + .set('Authorization', `Bearer ${token}`)
130 +
131 + expect(res.status).toBe(200)
132 +
133 + const dbRecord = await db.careAction.findUnique({ where: { id: action.id } })
134 + expect(dbRecord).toBeNull()
135 + })
136 + })
api/tests/medicine-regimens/crud.test.ts
@@ -0,0 +1,196 @@
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 + afterAll(() => db.$disconnect())
10 + beforeEach(() => cleanupTestDb(db))
11 +
12 + async function seedRegimen(
13 + userId: number,
14 + overrides: { name?: string; active?: boolean } = {}
15 + ) {
16 + return db.medicineRegimen.create({
17 + data: {
18 + userId,
19 + name: overrides.name ?? 'Sertralina',
20 + dosage: '50mg',
21 + periodicity: 'DAILY',
22 + scheduledAt: [],
23 + active: overrides.active ?? true,
24 + },
25 + })
26 + }
27 +
28 + describe('POST /medicine-regimens', () => {
29 + it('creates a regimen 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('/medicine-regimens')
35 + .set('Authorization', `Bearer ${token}`)
36 + .send({
37 + regimen: {
38 + name: 'Clonazepam',
39 + dosage: '0.5mg',
40 + periodicity: 'DAILY',
41 + scheduledAt: ['08:00', '20:00'],
42 + },
43 + })
44 +
45 + expect(res.status).toBe(201)
46 + expect(res.body.regimen.name).toBe('Clonazepam')
47 + expect(res.body.regimen.active).toBe(true)
48 + expect(res.body.regimen.scheduledAt).toEqual(['08:00', '20:00'])
49 +
50 + const dbRecord = await db.medicineRegimen.findFirst({
51 + where: { userId: user.id }
52 + })
53 +
54 + expect(dbRecord).not.toBeNull()
55 + })
56 +
57 + it('returns 400 for missing required fields', async () => {
58 + const user = await createTestUser(db)
59 + const token = generateTestToken(user.id, user.email)
60 +
61 + const res = await request(app)
62 + .post('/medicine-regimens')
63 + .set('Authorization', `Bearer ${token}`)
64 + .send({ regimen: { name: 'X' } })
65 +
66 + expect(res.status).toBe(400)
67 + })
68 + })
69 +
70 + describe('GET /medicine-regimens', () => {
71 + it('returns all regimens for the user', async () => {
72 + const user = await createTestUser(db)
73 + const other = await createTestUser(db, { email: 'other@example.com' })
74 + const token = generateTestToken(user.id, user.email)
75 +
76 + await seedRegimen(user.id, { name: 'Sertralina' })
77 + await seedRegimen(user.id, { name: 'Ritalina' })
78 + await seedRegimen(other.id, { name: 'OutroMed' })
79 +
80 + const res = await request(app)
81 + .get('/medicine-regimens')
82 + .set('Authorization', `Bearer ${token}`)
83 +
84 + expect(res.status).toBe(200)
85 + expect(res.body.regimens).toHaveLength(2)
86 + expect(res.body.regimens.every((r: any) => r.userId === user.id)).toBe(true)
87 + })
88 + })
89 +
90 + describe('GET /medicine-regimens/:id', () => {
91 + it('returns a single regimen', async () => {
92 + const user = await createTestUser(db)
93 + const token = generateTestToken(user.id, user.email)
94 + const regimen = await seedRegimen(user.id)
95 +
96 + const res = await request(app)
97 + .get(`/medicine-regimens/${regimen.id}`)
98 + .set('Authorization', `Bearer ${token}`)
99 +
100 + expect(res.status).toBe(200)
101 + expect(res.body.regimen.id).toBe(regimen.id)
102 + expect(res.body.regimen.name).toBe('Sertralina')
103 + })
104 +
105 + it('returns 404 for a regimen belonging to another user', async () => {
106 + const user = await createTestUser(db)
107 + const other = await createTestUser(db, { email: 'other@example.com' })
108 + const token = generateTestToken(user.id, user.email)
109 + const regimen = await seedRegimen(other.id)
110 +
111 + const res = await request(app)
112 + .get(`/medicine-regimens/${regimen.id}`)
113 + .set('Authorization', `Bearer ${token}`)
114 +
115 + expect(res.status).toBe(404)
116 + })
117 + })
118 +
119 + describe('PATCH /medicine-regimens/:id', () => {
120 + it('updates regimen fields', async () => {
121 + const user = await createTestUser(db)
122 + const token = generateTestToken(user.id, user.email)
123 + const regimen = await seedRegimen(user.id)
124 +
125 + const res = await request(app)
126 + .patch(`/medicine-regimens/${regimen.id}`)
127 + .set('Authorization', `Bearer ${token}`)
128 + .send({ regimen: { dosage: '100mg', scheduledAt: ['09:00'] } })
129 +
130 + expect(res.status).toBe(200)
131 + expect(res.body.regimen.dosage).toBe('100mg')
132 + expect(res.body.regimen.scheduledAt).toEqual(['09:00'])
133 + })
134 + })
135 +
136 + describe('PATCH /medicine-regimens/:id/active', () => {
137 + it('deactivates a regimen', async () => {
138 + const user = await createTestUser(db)
139 + const token = generateTestToken(user.id, user.email)
140 + const regimen = await seedRegimen(user.id, { active: true })
141 +
142 + const res = await request(app)
143 + .patch(`/medicine-regimens/${regimen.id}/active`)
144 + .set('Authorization', `Bearer ${token}`)
145 + .send({ active: false })
146 +
147 + expect(res.status).toBe(200)
148 + expect(res.body.regimen.active).toBe(false)
149 +
150 + const dbRecord = await db.medicineRegimen.findUnique({
151 + where: { id: regimen.id }
152 + })
153 +
154 + expect(dbRecord!.active).toBe(false)
155 + })
156 + })
157 +
158 + describe('DELETE /medicine-regimens/:id', () => {
159 + it('deactivates (soft-deletes) the regimen', async () => {
160 + const user = await createTestUser(db)
161 + const token = generateTestToken(user.id, user.email)
162 + const regimen = await seedRegimen(user.id, { active: true })
163 +
164 + const res = await request(app)
165 + .delete(`/medicine-regimens/${regimen.id}`)
166 + .set('Authorization', `Bearer ${token}`)
167 +
168 + expect(res.status).toBe(200)
169 +
170 + const dbRecord = await db.medicineRegimen.findUnique({
171 + where: { id: regimen.id }
172 + })
173 +
174 + expect(dbRecord).not.toBeNull()
175 + expect(dbRecord!.active).toBe(false)
176 + })
177 + })
178 +
179 + describe('GET /medicine-regimens/today', () => {
180 + it('returns active regimens with their logs', async () => {
181 + const user = await createTestUser(db)
182 + const token = generateTestToken(user.id, user.email)
183 +
184 + await seedRegimen(user.id, { name: 'Melatonina', active: true })
185 + await seedRegimen(user.id, { name: 'Inativa', active: false })
186 +
187 + const res = await request(app)
188 + .get('/medicine-regimens/today')
189 + .set('Authorization', `Bearer ${token}`)
190 +
191 + expect(res.status).toBe(200)
192 + expect(res.body.regimens).toHaveLength(1)
193 + expect(res.body.regimens[0].regimen.name).toBe('Melatonina')
194 + expect(res.body.regimens[0].logs).toBeInstanceOf(Array)
195 + })
196 + })