Coverage for tests/route_tests/test_employer.py: 100%

155 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-05-05 14:02 +0000

1"""Test for the employer routes.""" 

2 

3# pylint: disable=redefined-outer-name 

4# flake8: noqa: F811 

5 

6import os 

7import sys 

8import uuid 

9from unittest.mock import patch 

10from itsdangerous import URLSafeSerializer 

11import pytest 

12from dotenv import load_dotenv 

13 

14# Add the root directory to the Python path 

15sys.path.append( 

16 os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) 

17) 

18 

19from core import shared 

20from core.database_mongo_manager import DatabaseMongoManager 

21 

22os.environ["IS_TEST"] = "True" 

23 

24load_dotenv() 

25 

26 

27@pytest.fixture() 

28def client(): 

29 """Fixture to create a test client.""" 

30 from ...app import app # pylint: disable=import-outside-toplevel 

31 

32 app.config["TESTING"] = True 

33 return app.test_client() 

34 

35 

36@pytest.fixture() 

37def database(): 

38 """Fixture to create a test database.""" 

39 

40 database = DatabaseMongoManager( 

41 shared.getenv("MONGO_URI"), shared.getenv("MONGO_DB_TEST", "cs3528_testing") 

42 ) 

43 deadlines = database.get_all("deadline") 

44 database.delete_all("deadline") 

45 yield database 

46 

47 database.delete_all("deadline") 

48 for deadline in deadlines: 

49 database.insert("deadline", deadline) 

50 

51 # Cleanup code 

52 database.connection.close() 

53 

54 

55@pytest.fixture() 

56def employer_logged_in_client(client, database: DatabaseMongoManager): 

57 """Fixture to login an employer.""" 

58 database.add_table("employers") 

59 database.delete_all_by_field("employers", "email", "dummy@dummy.com") 

60 

61 employer = { 

62 "_id": uuid.uuid4().hex, 

63 "company_name": "dummy", 

64 "email": "dummy@dummy.com", 

65 } 

66 

67 database.insert("employers", employer) 

68 

69 url = "/employers/login" 

70 client.post( 

71 url, 

72 data={"email": "dummy@dummy.com"}, 

73 content_type="application/x-www-form-urlencoded", 

74 ) 

75 otp_serializer = URLSafeSerializer(str(shared.getenv("SECRET_KEY", "secret"))) 

76 with client.session_transaction() as session: 

77 otp = otp_serializer.loads(session["OTP"]) 

78 

79 url = "/employers/otp" 

80 client.post( 

81 url, 

82 data={"otp": otp}, 

83 content_type="application/x-www-form-urlencoded", 

84 ) 

85 

86 yield client 

87 

88 database.delete_all_by_field("employers", "email", "dummy@dummy.com") 

89 

90 with client.session_transaction() as session: 

91 session.clear() 

92 

93 

94def test_employer_otp_no_login(client): 

95 """Test OTP endpoint when employer is not logged in.""" 

96 response = client.post("/employers/otp", data={"otp": "123456"}) 

97 assert response.status_code == 400 

98 assert response.json == {"error": "Employer not logged in."} 

99 

100 

101def test_employer_otp_no_otp(client): 

102 """Test OTP endpoint when OTP is not in session.""" 

103 with client.session_transaction() as session: 

104 session["employer"] = {"_id": "123"} 

105 

106 response = client.post("/employers/otp", data={"otp": "123456"}) 

107 assert response.status_code == 400 

108 assert response.json == {"error": "OTP not sent."} 

109 

110 

111def test_employer_login_page(client): 

112 """Test the employer login page.""" 

113 url = "/employers/login" 

114 

115 response = client.get(url) 

116 assert response.status_code == 200 

117 

118 

119def test_employer_home_page(employer_logged_in_client): 

120 """Test the employer home page.""" 

121 url = "/employers/home" 

122 

123 response = employer_logged_in_client.get(url) 

124 assert response.status_code == 200 

125 

126 

127def test_search_opportunities_page(employer_logged_in_client): 

128 """Test the search_opportunities page.""" 

129 url = "/opportunities/search" 

130 

131 response = employer_logged_in_client.get(url) 

132 assert response.status_code == 200 

133 

134 

135def test_employer_delete_opportunity_page_no_opportunity_id(employer_logged_in_client): 

136 """Test the employer_delete_opportunity page.""" 

137 url = "/opportunities/employer_delete_opportunity" 

138 

139 response = employer_logged_in_client.get(url) 

140 assert response.status_code == 302 

141 

142 

143def test_employers_rank_students_no_opportunity_id(employer_logged_in_client): 

144 """Test the rank_students page without providing an opportunity ID.""" 

145 

146 url = "/employers/rank_students" # No opportunity_id in the request 

147 

148 with patch( 

149 "app.DEADLINE_MANAGER.is_past_opportunities_ranking_deadline", 

150 return_value=False, 

151 ): 

152 response = employer_logged_in_client.get(url) # GET request 

153 

154 assert response.status_code == 400 

155 assert response.json == {"error": "Need opportunity ID."} 

156 

157 

158def test_employers_rank_students_past_opportunities_deadline( 

159 employer_logged_in_client, database 

160): 

161 """Test the rank_students page.""" 

162 url = "/employers/rank_students" 

163 

164 database.insert("deadline", {"type": 0, "deadline": "2022-10-10"}) 

165 database.insert("deadline", {"type": 1, "deadline": "2022-10-12"}) 

166 database.insert("deadline", {"type": 2, "deadline": "2022-10-15"}) 

167 

168 response = employer_logged_in_client.get(url) 

169 assert response.status_code == 200 

170 assert b"Ranking deadline has passed as of 2022-10-15" in response.data 

171 

172 

173def test_employers_rank_students_wrong_opportunity_id( 

174 employer_logged_in_client, database 

175): 

176 """Test the rank_students page with an incorrect opportunity_id.""" 

177 

178 url = "/employers/rank_students?opportunity_id=123" # Pass opportunity_id in query string 

179 database.delete_all_by_field("opportunities", "_id", "123") 

180 database.insert("opportunities", {"_id": "123", "employer_id": "23424"}) 

181 

182 with patch( 

183 "app.DEADLINE_MANAGER.is_past_opportunities_ranking_deadline", 

184 return_value=False, 

185 ): 

186 response = employer_logged_in_client.get(url) # GET request 

187 

188 assert response.status_code == 400 

189 assert response.json == {"error": "Employer does not own this opportunity."} 

190 

191 database.delete_all_by_field("opportunities", "_id", "123") 

192 

193 

194def test_employers_rank_students_past_student_ranking_deadline( 

195 employer_logged_in_client, database 

196): 

197 """Test that employers cannot rank students before the student ranking deadline has passed.""" 

198 

199 url = "/employers/rank_students?opportunity_id=123" 

200 database.delete_all_by_field("opportunities", "_id", "123") 

201 database.insert("opportunities", {"_id": "123", "employer_id": "test_employer_id"}) 

202 

203 with employer_logged_in_client.session_transaction() as session: 

204 session["employer"] = {"_id": "test_employer_id"} 

205 

206 # Use patch directly 

207 with patch( 

208 "app.DEADLINE_MANAGER.is_past_opportunities_ranking_deadline", 

209 return_value=False, 

210 ), patch( 

211 "app.DEADLINE_MANAGER.is_past_student_ranking_deadline", return_value=False 

212 ), patch( 

213 "app.DEADLINE_MANAGER.get_student_ranking_deadline", return_value="2025-10-15" 

214 ): 

215 

216 response = employer_logged_in_client.get(url) 

217 

218 assert response.status_code == 200 

219 assert ( 

220 b"Student ranking deadline must have passed before you can start, wait till 2025-10-15" 

221 in response.data 

222 ) 

223 

224 database.delete_all_by_field("opportunities", "_id", "123") 

225 

226 

227def test_employer_update_opportunity(employer_logged_in_client): 

228 """Test the employer_update_opportunity page.""" 

229 url = "/opportunities/employer_add_update_opportunity" 

230 

231 with patch("app.DEADLINE_MANAGER.is_past_details_deadline", return_value=True): 

232 response = employer_logged_in_client.get(url) 

233 

234 assert response.status_code == 200 

235 assert b"Adding/Updating details deadline has passed as of " in response.data 

236 

237 

238def test_employer_add_opportunity_post(employer_logged_in_client, database): 

239 """Test the employer_update_opportunity page.""" 

240 url = "/opportunities/employer_add_update_opportunity" 

241 

242 database.delete_all_by_field("opportunities", "_id", "123") 

243 database.delete_all_by_field("opportunities", "_id", "1234") 

244 opportunity = { 

245 "_id": "1234", 

246 "title": "Software Internship", 

247 "description": "A great opportunity to learn.", 

248 "url": "https://example.com", 

249 "location": "Remote", 

250 "modules_required": '["CS101", "CS102"]', # Matches how the request expects it 

251 "courses_required": '["Computer_Science"]', 

252 "spots_available": 3, 

253 "duration": "6_months", 

254 } 

255 

256 with patch("app.DEADLINE_MANAGER.is_past_details_deadline", return_value=False): 

257 response = employer_logged_in_client.post( 

258 url, data=opportunity, content_type="application/x-www-form-urlencoded" 

259 ) 

260 

261 assert response.status_code == 200 # Adjust based on actual expected behaviour 

262 database.delete_by_id("opportunities", "1234") 

263 database.delete_all_by_field("employers", "email", "dummy@dummy,com") 

264 

265 

266def test_employer_add_opportunity_post_different_employer_id( 

267 employer_logged_in_client, database 

268): 

269 """Test the employer_update_opportunity page.""" 

270 url = "/opportunities/employer_add_update_opportunity" 

271 

272 database.delete_all_by_field("opportunities", "_id", "123") 

273 database.delete_all_by_field("opportunities", "_id", "1234") 

274 opportunity = { 

275 "_id": "123", 

276 "title": "Software Internship", 

277 "description": "A great opportunity to learn.", 

278 "url": "https://example.com", 

279 "location": "Remote", 

280 "modules_required": '["CS101", "CS102"]', # Matches how the request expects it 

281 "courses_required": '["Computer_Science"]', 

282 "spots_available": 3, 

283 "duration": "6_months", 

284 } 

285 database.insert("opportunities", {"_id": "123", "employer_id": "test_employer_id"}) 

286 

287 with patch("app.DEADLINE_MANAGER.is_past_details_deadline", return_value=False): 

288 response = employer_logged_in_client.post( 

289 url, data=opportunity, content_type="application/x-www-form-urlencoded" 

290 ) 

291 

292 assert response.status_code == 401 

293 assert response.json == {"error": "Unauthorized Access."} 

294 database.delete_by_id("opportunities", "123") 

295 database.delete_all_by_field("employers", "email", "dummy@dummy,com") 

296 

297 

298def test_get_opportunity_page_no_id(employer_logged_in_client): 

299 """Test retrieving an opportunity without an ID, ensuring UUID is generated.""" 

300 url = "/opportunities/employer_add_update_opportunity" # No opportunity_id 

301 

302 with patch("app.DEADLINE_MANAGER.is_past_details_deadline", return_value=False): 

303 response = employer_logged_in_client.get(url) 

304 

305 assert response.status_code == 200 

306 

307 

308def test_get_opportunity_page_with_id(employer_logged_in_client, database): 

309 """Test retrieving an opportunity with an ID.""" 

310 url = "/opportunities/employer_add_update_opportunity?opportunity_id=123" # Pass opportunity 

311 

312 database.delete_all_by_field("opportunities", "_id", "123") 

313 database.insert( 

314 "opportunities", 

315 {"_id": "123", "employer_id": "test_employer_id", "spots_available": 1}, 

316 ) 

317 

318 with patch("app.DEADLINE_MANAGER.is_past_details_deadline", return_value=False): 

319 response = employer_logged_in_client.get(url) 

320 

321 assert response.status_code == 200 

322 

323 

324def test_employers_rank_students_success(employer_logged_in_client, database): 

325 """Test the rank_students page.""" 

326 url = "/employers/rank_students?opportunity_id=123" 

327 database.delete_all_by_field("opportunities", "_id", "123") 

328 database.insert("opportunities", {"_id": "123", "employer_id": "test_employer_id"}) 

329 

330 with employer_logged_in_client.session_transaction() as session: 

331 session["employer"] = {"_id": "test_employer_id"} 

332 

333 with patch( 

334 "app.DEADLINE_MANAGER.is_past_opportunities_ranking_deadline", 

335 return_value=False, 

336 ), patch( 

337 "app.DEADLINE_MANAGER.is_past_student_ranking_deadline", return_value=True 

338 ): 

339 

340 response = employer_logged_in_client.get(url) 

341 

342 assert response.status_code == 200 

343 

344 database.delete_all_by_field("opportunities", "_id", "123") 

345 database.delete_all_by_field("employers", "_id", "test_employer_id")