@@ -72,6 +72,27 @@ def test_update_cycle_future_date(self, client, auth_headers):
7272 }, headers = auth_headers )
7373 assert resp .status_code == 400
7474
75+ def test_update_cycle_cross_user_denied (self , client ):
76+ user_a_headers = {"Content-Type" : "application/json" , "X-User-Id" : "user_a" }
77+ user_b_headers = {"Content-Type" : "application/json" , "X-User-Id" : "user_b" }
78+
79+ create = client .post ("/add-cycle" , json = {
80+ "startDate" : "2026-03-01" ,
81+ "endDate" : "2026-03-05" ,
82+ }, headers = user_a_headers )
83+ assert create .status_code == 201
84+ cycle_id = create .get_json ()["cycle" ]["id" ]
85+
86+ resp = client .put (f"/cycles/{ cycle_id } " , json = {
87+ "startDate" : "2026-03-02" ,
88+ "endDate" : "2026-03-06" ,
89+ }, headers = user_b_headers )
90+ assert resp .status_code in [403 , 404 ]
91+
92+ get_resp = client .get (f"/cycles/{ cycle_id } " , headers = user_a_headers )
93+ assert get_resp .status_code == 200
94+ assert get_resp .get_json ()["cycle" ]["startDate" ] == "2026-03-01"
95+
7596
7697class TestDeleteCycle :
7798 """DELETE /cycles/:id"""
@@ -103,6 +124,23 @@ def test_delete_cycle_removes_from_list(self, client, auth_headers):
103124 cycle_ids = [c ["id" ] for c in cycles_resp .get_json ()["cycles" ]]
104125 assert cycle_id not in cycle_ids
105126
127+ def test_delete_cycle_cross_user_denied (self , client ):
128+ user_a_headers = {"Content-Type" : "application/json" , "X-User-Id" : "user_a" }
129+ user_b_headers = {"Content-Type" : "application/json" , "X-User-Id" : "user_b" }
130+
131+ create = client .post ("/add-cycle" , json = {
132+ "startDate" : "2026-05-01" ,
133+ "endDate" : "2026-05-05" ,
134+ }, headers = user_a_headers )
135+ cycle_id = create .get_json ()["cycle" ]["id" ]
136+
137+ resp = client .delete (f"/cycles/{ cycle_id } " , headers = user_b_headers )
138+ assert resp .status_code in [403 , 404 ]
139+
140+ get_resp = client .get (f"/cycles/{ cycle_id } " , headers = user_a_headers )
141+ assert get_resp .status_code == 200
142+ assert get_resp .get_json ()["cycle" ]["id" ] == cycle_id
143+
106144
107145class TestUpdateSymptom :
108146 """PUT /symptoms/:id"""
@@ -154,4 +192,52 @@ def test_update_symptom_invalid_severity(self, client, auth_headers):
154192 uid = "test_user_001"
155193 mock_symptoms [uid ] = [{"id" : "sym_sev_1" , "type" : "Cramps" , "severity" : "Low" , "date" : "2026-05-20" }]
156194
157- resp = client .put ("/ symptoms / sym
195+ resp = client .put ("/symptoms/sym_sev_1" , json = {
196+ "type" : "Cramps" ,
197+ "severity" : "InvalidSeverity" ,
198+ "date" : "2026-05-20" ,
199+ }, headers = auth_headers )
200+ assert resp .status_code == 400
201+
202+ def test_update_symptom_cross_user_denied (self , client ):
203+ from app import mock_symptoms
204+ user_b_headers = {"Content-Type" : "application/json" , "X-User-Id" : "user_b" }
205+ mock_symptoms ["user_a" ] = [{"id" : "sym_user_a" , "type" : "Cramps" , "severity" : "Low" , "date" : "2026-05-20" }]
206+
207+ resp = client .put ("/symptoms/sym_user_a" , json = {
208+ "type" : "Headache" ,
209+ "severity" : "High" ,
210+ "date" : "2026-05-21" ,
211+ }, headers = user_b_headers )
212+ assert resp .status_code in [403 , 404 ]
213+
214+ assert mock_symptoms ["user_a" ][0 ]["type" ] == "Cramps"
215+ assert mock_symptoms ["user_a" ][0 ]["severity" ] == "Low"
216+
217+
218+ class TestDeleteSymptom :
219+ """DELETE /symptoms/:id"""
220+
221+ def test_delete_symptom_success (self , client , auth_headers ):
222+ from app import mock_symptoms
223+ uid = "test_user_001"
224+ mock_symptoms [uid ] = [{"id" : "sym_del_1" , "type" : "Cramps" , "severity" : "Low" , "date" : "2026-05-20" }]
225+
226+ resp = client .delete ("/symptoms/sym_del_1" , headers = auth_headers )
227+ assert resp .status_code == 200
228+ assert mock_symptoms [uid ] == []
229+
230+ def test_delete_symptom_not_found (self , client , auth_headers ):
231+ resp = client .delete ("/symptoms/nonexistent_id" , headers = auth_headers )
232+ assert resp .status_code == 404
233+
234+ def test_delete_symptom_cross_user_denied (self , client ):
235+ from app import mock_symptoms
236+ user_b_headers = {"Content-Type" : "application/json" , "X-User-Id" : "user_b" }
237+ mock_symptoms ["user_a" ] = [{"id" : "sym_del_user_a" , "type" : "Fatigue" , "severity" : "Medium" , "date" : "2026-05-22" }]
238+
239+ resp = client .delete ("/symptoms/sym_del_user_a" , headers = user_b_headers )
240+ assert resp .status_code in [403 , 404 ]
241+
242+ assert len (mock_symptoms ["user_a" ]) == 1
243+ assert mock_symptoms ["user_a" ][0 ]["id" ] == "sym_del_user_a"
0 commit comments