Coverage for src/tests/test_api.py: 100%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

547 statements  

1from datetime import timedelta 

2 

3import grpc 

4import pytest 

5from google.protobuf import empty_pb2, wrappers_pb2 

6 

7from couchers import errors 

8from couchers.db import session_scope 

9from couchers.models import FriendRelationship, FriendStatus 

10from couchers.sql import couchers_select as select 

11from couchers.utils import create_coordinate, to_aware_datetime 

12from proto import api_pb2, jail_pb2 

13from tests.test_fixtures import ( # noqa 

14 api_session, 

15 blocking_session, 

16 db, 

17 generate_user, 

18 make_friends, 

19 make_user_block, 

20 make_user_invisible, 

21 real_api_session, 

22 real_jail_session, 

23 testconfig, 

24) 

25 

26 

27@pytest.fixture(autouse=True) 

28def _(testconfig): 

29 pass 

30 

31 

32def test_ping(db): 

33 user, token = generate_user() 

34 

35 with real_api_session(token) as api: 

36 res = api.Ping(api_pb2.PingReq()) 

37 

38 assert res.user.user_id == user.id 

39 assert res.user.username == user.username 

40 assert res.user.name == user.name 

41 assert res.user.city == user.city 

42 assert res.user.hometown == user.hometown 

43 assert res.user.verification == 0.0 

44 assert res.user.community_standing == user.community_standing 

45 assert res.user.num_references == 0 

46 assert res.user.gender == user.gender 

47 assert res.user.pronouns == user.pronouns 

48 assert res.user.age == user.age 

49 

50 assert (res.user.lat, res.user.lng) == (user.coordinates or (0, 0)) 

51 

52 # the joined time is fuzzed 

53 # but shouldn't be before actual joined time, or more than one hour behind 

54 assert user.joined - timedelta(hours=1) <= to_aware_datetime(res.user.joined) <= user.joined 

55 # same for last_active 

56 assert user.last_active - timedelta(hours=1) <= to_aware_datetime(res.user.last_active) <= user.last_active 

57 

58 assert res.user.hosting_status == api_pb2.HOSTING_STATUS_CANT_HOST 

59 assert res.user.meetup_status == api_pb2.MEETUP_STATUS_OPEN_TO_MEETUP 

60 

61 assert res.user.occupation == user.occupation 

62 assert res.user.education == user.education 

63 assert res.user.about_me == user.about_me 

64 assert res.user.my_travels == user.my_travels 

65 assert res.user.things_i_like == user.things_i_like 

66 assert set(language_ability.code for language_ability in res.user.language_abilities) == set(["fin", "fra"]) 

67 assert res.user.about_place == user.about_place 

68 assert res.user.regions_visited == ["FIN", "REU", "CHE"] # Tests alphabetization by region name 

69 assert res.user.regions_lived == ["EST", "FRA", "ESP"] # Ditto 

70 assert res.user.additional_information == user.additional_information 

71 

72 assert res.user.friends == api_pb2.User.FriendshipStatus.NA 

73 assert not res.user.HasField("pending_friend_request") 

74 

75 

76def test_coords(db): 

77 # make them have not added a location 

78 user1, token1 = generate_user(geom=None, geom_radius=None) 

79 user2, token2 = generate_user() 

80 

81 with api_session(token2) as api: 

82 res = api.Ping(api_pb2.PingReq()) 

83 assert res.user.city == user2.city 

84 lat, lng = user2.coordinates or (0, 0) 

85 assert res.user.lat == lat 

86 assert res.user.lng == lng 

87 assert res.user.radius == user2.geom_radius 

88 

89 with api_session(token2) as api: 

90 res = api.GetUser(api_pb2.GetUserReq(user=user1.username)) 

91 assert res.city == user1.city 

92 assert res.lat == 0.0 

93 assert res.lng == 0.0 

94 assert res.radius == 0.0 

95 

96 # Check coordinate wrapping 

97 user3, token3 = generate_user(geom=create_coordinate(40.0, -180.5)) 

98 user4, token4 = generate_user(geom=create_coordinate(40.0, 20.0)) 

99 user5, token5 = generate_user(geom=create_coordinate(90.5, 20.0)) 

100 

101 with api_session(token3) as api: 

102 res = api.GetUser(api_pb2.GetUserReq(user=user3.username)) 

103 assert res.lat == 40.0 

104 assert res.lng == 179.5 

105 

106 with api_session(token4) as api: 

107 res = api.GetUser(api_pb2.GetUserReq(user=user4.username)) 

108 assert res.lat == 40.0 

109 assert res.lng == 20.0 

110 

111 # PostGIS does not wrap longitude for latitude overflow 

112 with api_session(token5) as api: 

113 res = api.GetUser(api_pb2.GetUserReq(user=user5.username)) 

114 assert res.lat == 89.5 

115 assert res.lng == 20.0 

116 

117 with real_jail_session(token1) as jail: 

118 res = jail.JailInfo(empty_pb2.Empty()) 

119 assert res.jailed 

120 assert res.has_not_added_location 

121 

122 res = jail.SetLocation( 

123 jail_pb2.SetLocationReq( 

124 city="New York City", 

125 lat=40.7812, 

126 lng=-73.9647, 

127 radius=250, 

128 ) 

129 ) 

130 

131 assert not res.jailed 

132 assert not res.has_not_added_location 

133 

134 res = jail.JailInfo(empty_pb2.Empty()) 

135 assert not res.jailed 

136 assert not res.has_not_added_location 

137 

138 with api_session(token2) as api: 

139 res = api.GetUser(api_pb2.GetUserReq(user=user1.username)) 

140 assert res.city == "New York City" 

141 assert res.lat == 40.7812 

142 assert res.lng == -73.9647 

143 assert res.radius == 250 

144 

145 

146def test_get_user(db): 

147 user1, token1 = generate_user() 

148 user2, token2 = generate_user() 

149 

150 with api_session(token1) as api: 

151 res = api.GetUser(api_pb2.GetUserReq(user=user2.username)) 

152 assert res.user_id == user2.id 

153 assert res.username == user2.username 

154 assert res.name == user2.name 

155 

156 with api_session(token1) as api: 

157 res = api.GetUser(api_pb2.GetUserReq(user=str(user2.id))) 

158 assert res.user_id == user2.id 

159 assert res.username == user2.username 

160 assert res.name == user2.name 

161 

162 

163def test_update_profile(db): 

164 user, token = generate_user() 

165 

166 with api_session(token) as api: 

167 with pytest.raises(grpc.RpcError) as e: 

168 api.UpdateProfile(api_pb2.UpdateProfileReq(name=wrappers_pb2.StringValue(value=" "))) 

169 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

170 assert e.value.details() == errors.INVALID_NAME 

171 

172 with pytest.raises(grpc.RpcError) as e: 

173 api.UpdateProfile( 

174 api_pb2.UpdateProfileReq(lat=wrappers_pb2.DoubleValue(value=0), lng=wrappers_pb2.DoubleValue(value=0)) 

175 ) 

176 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

177 assert e.value.details() == errors.INVALID_COORDINATE 

178 

179 with pytest.raises(grpc.RpcError) as e: 

180 api.UpdateProfile( 

181 api_pb2.UpdateProfileReq(regions_visited=api_pb2.RepeatedStringValue(value=["United States"])) 

182 ) 

183 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

184 assert e.value.details() == errors.INVALID_REGION 

185 

186 with pytest.raises(grpc.RpcError) as e: 

187 api.UpdateProfile( 

188 api_pb2.UpdateProfileReq(regions_lived=api_pb2.RepeatedStringValue(value=["United Kingdom"])) 

189 ) 

190 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

191 assert e.value.details() == errors.INVALID_REGION 

192 

193 api.UpdateProfile( 

194 api_pb2.UpdateProfileReq( 

195 name=wrappers_pb2.StringValue(value="New name"), 

196 city=wrappers_pb2.StringValue(value="Timbuktu"), 

197 hometown=api_pb2.NullableStringValue(value="Walla Walla"), 

198 lat=wrappers_pb2.DoubleValue(value=0.01), 

199 lng=wrappers_pb2.DoubleValue(value=-2), 

200 radius=wrappers_pb2.DoubleValue(value=321), 

201 pronouns=api_pb2.NullableStringValue(value="Ro, Robo, Robots"), 

202 occupation=api_pb2.NullableStringValue(value="Testing"), 

203 education=api_pb2.NullableStringValue(value="Couchers U"), 

204 about_me=api_pb2.NullableStringValue(value="I rule"), 

205 my_travels=api_pb2.NullableStringValue(value="Oh the places you'll go!"), 

206 things_i_like=api_pb2.NullableStringValue(value="Couchers"), 

207 about_place=api_pb2.NullableStringValue(value="My place"), 

208 hosting_status=api_pb2.HOSTING_STATUS_CAN_HOST, 

209 meetup_status=api_pb2.MEETUP_STATUS_WANTS_TO_MEETUP, 

210 language_abilities=api_pb2.RepeatedLanguageAbilityValue( 

211 value=[ 

212 api_pb2.LanguageAbility( 

213 code="eng", 

214 fluency=api_pb2.LanguageAbility.Fluency.FLUENCY_FLUENT, 

215 ) 

216 ], 

217 ), 

218 regions_visited=api_pb2.RepeatedStringValue(value=["CXR", "FIN"]), 

219 regions_lived=api_pb2.RepeatedStringValue(value=["USA", "EST"]), 

220 additional_information=api_pb2.NullableStringValue(value="I <3 Couchers"), 

221 ) 

222 ) 

223 

224 user_details = api.GetUser(api_pb2.GetUserReq(user=user.username)) 

225 assert user_details.name == "New name" 

226 assert user_details.city == "Timbuktu" 

227 assert user_details.hometown == "Walla Walla" 

228 assert user_details.pronouns == "Ro, Robo, Robots" 

229 assert user_details.education == "Couchers U" 

230 assert user_details.my_travels == "Oh the places you'll go!" 

231 assert user_details.things_i_like == "Couchers" 

232 assert user_details.lat == 0.01 

233 assert user_details.lng == -2 

234 assert user_details.radius == 321 

235 assert user_details.occupation == "Testing" 

236 assert user_details.about_me == "I rule" 

237 assert user_details.about_place == "My place" 

238 assert user_details.hosting_status == api_pb2.HOSTING_STATUS_CAN_HOST 

239 assert user_details.meetup_status == api_pb2.MEETUP_STATUS_WANTS_TO_MEETUP 

240 assert user_details.language_abilities[0].code == "eng" 

241 assert user_details.language_abilities[0].fluency == api_pb2.LanguageAbility.Fluency.FLUENCY_FLUENT 

242 assert user_details.additional_information == "I <3 Couchers" 

243 assert user_details.regions_visited == ["CXR", "FIN"] 

244 assert user_details.regions_lived == ["EST", "USA"] 

245 

246 # Test unset values 

247 api.UpdateProfile( 

248 api_pb2.UpdateProfileReq( 

249 hometown=api_pb2.NullableStringValue(is_null=True), 

250 radius=wrappers_pb2.DoubleValue(value=0), 

251 pronouns=api_pb2.NullableStringValue(is_null=True), 

252 occupation=api_pb2.NullableStringValue(is_null=True), 

253 education=api_pb2.NullableStringValue(is_null=True), 

254 about_me=api_pb2.NullableStringValue(is_null=True), 

255 my_travels=api_pb2.NullableStringValue(is_null=True), 

256 things_i_like=api_pb2.NullableStringValue(is_null=True), 

257 about_place=api_pb2.NullableStringValue(is_null=True), 

258 hosting_status=api_pb2.HOSTING_STATUS_CAN_HOST, 

259 meetup_status=api_pb2.MEETUP_STATUS_WANTS_TO_MEETUP, 

260 language_abilities=api_pb2.RepeatedLanguageAbilityValue(value=[]), 

261 regions_visited=api_pb2.RepeatedStringValue(value=[]), 

262 regions_lived=api_pb2.RepeatedStringValue(value=[]), 

263 additional_information=api_pb2.NullableStringValue(is_null=True), 

264 ) 

265 ) 

266 

267 user_details = api.GetUser(api_pb2.GetUserReq(user=user.username)) 

268 assert not user_details.hometown 

269 assert not user_details.radius 

270 assert not user_details.pronouns 

271 assert not user_details.occupation 

272 assert not user_details.education 

273 assert not user_details.about_me 

274 assert not user_details.my_travels 

275 assert not user_details.things_i_like 

276 assert not user_details.about_place 

277 assert user_details.hosting_status == api_pb2.HOSTING_STATUS_CAN_HOST 

278 assert user_details.meetup_status == api_pb2.MEETUP_STATUS_WANTS_TO_MEETUP 

279 assert not user_details.language_abilities 

280 assert not user_details.regions_visited 

281 assert not user_details.regions_lived 

282 assert not user_details.additional_information 

283 

284 

285def test_language_abilities(db): 

286 user, token = generate_user() 

287 

288 with api_session(token) as api: 

289 res = api.GetUser(api_pb2.GetUserReq(user=user.username)) 

290 assert len(res.language_abilities) == 2 

291 

292 # can't add non-existent languages 

293 with pytest.raises(grpc.RpcError) as e: 

294 res = api.UpdateProfile( 

295 api_pb2.UpdateProfileReq( 

296 language_abilities=api_pb2.RepeatedLanguageAbilityValue( 

297 value=[ 

298 api_pb2.LanguageAbility( 

299 code="QQQ", 

300 fluency=api_pb2.LanguageAbility.Fluency.FLUENCY_FLUENT, 

301 ) 

302 ], 

303 ), 

304 ) 

305 ) 

306 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

307 assert e.value.details() == errors.INVALID_LANGUAGE 

308 

309 # can't have multiple languages of the same type 

310 with pytest.raises(Exception) as e: 

311 res = api.UpdateProfile( 

312 api_pb2.UpdateProfileReq( 

313 language_abilities=api_pb2.RepeatedLanguageAbilityValue( 

314 value=[ 

315 api_pb2.LanguageAbility( 

316 code="eng", 

317 fluency=api_pb2.LanguageAbility.Fluency.FLUENCY_FLUENT, 

318 ), 

319 api_pb2.LanguageAbility( 

320 code="eng", 

321 fluency=api_pb2.LanguageAbility.Fluency.FLUENCY_FLUENT, 

322 ), 

323 ], 

324 ), 

325 ) 

326 ) 

327 assert "violates unique constraint" in str(e.value) 

328 

329 # nothing changed 

330 res = api.GetUser(api_pb2.GetUserReq(user=user.username)) 

331 assert len(res.language_abilities) == 2 

332 

333 # now actually add a value 

334 api.UpdateProfile( 

335 api_pb2.UpdateProfileReq( 

336 language_abilities=api_pb2.RepeatedLanguageAbilityValue( 

337 value=[ 

338 api_pb2.LanguageAbility( 

339 code="eng", 

340 fluency=api_pb2.LanguageAbility.Fluency.FLUENCY_FLUENT, 

341 ) 

342 ], 

343 ), 

344 ) 

345 ) 

346 

347 res = api.GetUser(api_pb2.GetUserReq(user=user.username)) 

348 assert len(res.language_abilities) == 1 

349 assert res.language_abilities[0].code == "eng" 

350 assert res.language_abilities[0].fluency == api_pb2.LanguageAbility.Fluency.FLUENCY_FLUENT 

351 

352 # change the value to a new one 

353 api.UpdateProfile( 

354 api_pb2.UpdateProfileReq( 

355 language_abilities=api_pb2.RepeatedLanguageAbilityValue( 

356 value=[ 

357 api_pb2.LanguageAbility( 

358 code="fin", 

359 fluency=api_pb2.LanguageAbility.Fluency.FLUENCY_BEGINNER, 

360 ) 

361 ], 

362 ), 

363 ) 

364 ) 

365 

366 res = api.GetUser(api_pb2.GetUserReq(user=user.username)) 

367 assert len(res.language_abilities) == 1 

368 assert res.language_abilities[0].code == "fin" 

369 assert res.language_abilities[0].fluency == api_pb2.LanguageAbility.Fluency.FLUENCY_BEGINNER 

370 

371 # should be able to set to same value still 

372 api.UpdateProfile( 

373 api_pb2.UpdateProfileReq( 

374 language_abilities=api_pb2.RepeatedLanguageAbilityValue( 

375 value=[ 

376 api_pb2.LanguageAbility( 

377 code="fin", 

378 fluency=api_pb2.LanguageAbility.Fluency.FLUENCY_BEGINNER, 

379 ) 

380 ], 

381 ), 

382 ) 

383 ) 

384 

385 res = api.GetUser(api_pb2.GetUserReq(user=user.username)) 

386 assert len(res.language_abilities) == 1 

387 assert res.language_abilities[0].code == "fin" 

388 assert res.language_abilities[0].fluency == api_pb2.LanguageAbility.Fluency.FLUENCY_BEGINNER 

389 

390 # don't change it 

391 api.UpdateProfile(api_pb2.UpdateProfileReq()) 

392 

393 res = api.GetUser(api_pb2.GetUserReq(user=user.username)) 

394 assert len(res.language_abilities) == 1 

395 assert res.language_abilities[0].code == "fin" 

396 assert res.language_abilities[0].fluency == api_pb2.LanguageAbility.Fluency.FLUENCY_BEGINNER 

397 

398 # remove value 

399 api.UpdateProfile( 

400 api_pb2.UpdateProfileReq( 

401 language_abilities=api_pb2.RepeatedLanguageAbilityValue( 

402 value=[], 

403 ), 

404 ) 

405 ) 

406 

407 res = api.GetUser(api_pb2.GetUserReq(user=user.username)) 

408 assert len(res.language_abilities) == 0 

409 

410 

411def test_pending_friend_request_count(db): 

412 user1, token1 = generate_user() 

413 user2, token2 = generate_user() 

414 user3, token3 = generate_user() 

415 

416 with api_session(token2) as api: 

417 res = api.Ping(api_pb2.PingReq()) 

418 assert res.pending_friend_request_count == 0 

419 

420 with api_session(token1) as api: 

421 res = api.Ping(api_pb2.PingReq()) 

422 assert res.pending_friend_request_count == 0 

423 api.SendFriendRequest(api_pb2.SendFriendRequestReq(user_id=user2.id)) 

424 res = api.Ping(api_pb2.PingReq()) 

425 assert res.pending_friend_request_count == 0 

426 

427 with api_session(token2) as api: 

428 res = api.Ping(api_pb2.PingReq()) 

429 assert res.pending_friend_request_count == 1 

430 

431 with api_session(token2) as api: 

432 # check it's there 

433 res = api.ListFriendRequests(empty_pb2.Empty()) 

434 assert len(res.sent) == 0 

435 assert len(res.received) == 1 

436 

437 assert res.received[0].state == api_pb2.FriendRequest.FriendRequestStatus.PENDING 

438 assert res.received[0].user_id == user1.id 

439 

440 fr_id = res.received[0].friend_request_id 

441 

442 # accept it 

443 api.RespondFriendRequest(api_pb2.RespondFriendRequestReq(friend_request_id=fr_id, accept=True)) 

444 

445 res = api.Ping(api_pb2.PingReq()) 

446 assert res.pending_friend_request_count == 0 

447 

448 

449def test_friend_request_flow(db): 

450 user1, token1 = generate_user() 

451 user2, token2 = generate_user() 

452 user3, token3 = generate_user() 

453 

454 # send friend request from user1 to user2 

455 with api_session(token1) as api: 

456 api.SendFriendRequest(api_pb2.SendFriendRequestReq(user_id=user2.id)) 

457 

458 with session_scope() as session: 

459 friend_request_id = ( 

460 session.execute( 

461 select(FriendRelationship).where( 

462 FriendRelationship.from_user_id == user1.id and FriendRelationship.to_user_id == user2.id 

463 ) 

464 ).scalar_one_or_none() 

465 ).id 

466 

467 with api_session(token1) as api: 

468 # check it went through 

469 res = api.ListFriendRequests(empty_pb2.Empty()) 

470 assert len(res.sent) == 1 

471 assert len(res.received) == 0 

472 

473 assert res.sent[0].state == api_pb2.FriendRequest.FriendRequestStatus.PENDING 

474 assert res.sent[0].user_id == user2.id 

475 assert res.sent[0].friend_request_id == friend_request_id 

476 

477 with api_session(token2) as api: 

478 # check it's there 

479 res = api.ListFriendRequests(empty_pb2.Empty()) 

480 assert len(res.sent) == 0 

481 assert len(res.received) == 1 

482 

483 assert res.received[0].state == api_pb2.FriendRequest.FriendRequestStatus.PENDING 

484 assert res.received[0].user_id == user1.id 

485 

486 fr_id = res.received[0].friend_request_id 

487 

488 # accept it 

489 api.RespondFriendRequest(api_pb2.RespondFriendRequestReq(friend_request_id=fr_id, accept=True)) 

490 

491 # check it's gone 

492 res = api.ListFriendRequests(empty_pb2.Empty()) 

493 assert len(res.sent) == 0 

494 assert len(res.received) == 0 

495 

496 # check we're friends now 

497 res = api.ListFriends(empty_pb2.Empty()) 

498 assert len(res.user_ids) == 1 

499 assert res.user_ids[0] == user1.id 

500 

501 with api_session(token1) as api: 

502 # check it's gone 

503 res = api.ListFriendRequests(empty_pb2.Empty()) 

504 assert len(res.sent) == 0 

505 assert len(res.received) == 0 

506 

507 # check we're friends now 

508 res = api.ListFriends(empty_pb2.Empty()) 

509 assert len(res.user_ids) == 1 

510 assert res.user_ids[0] == user2.id 

511 

512 

513def test_cant_friend_request_twice(db): 

514 user1, token1 = generate_user() 

515 user2, token2 = generate_user() 

516 

517 # send friend request from user1 to user2 

518 with api_session(token1) as api: 

519 api.SendFriendRequest(api_pb2.SendFriendRequestReq(user_id=user2.id)) 

520 

521 with pytest.raises(grpc.RpcError) as e: 

522 api.SendFriendRequest(api_pb2.SendFriendRequestReq(user_id=user2.id)) 

523 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

524 assert e.value.details() == errors.FRIENDS_ALREADY_OR_PENDING 

525 

526 

527def test_cant_friend_request_pending(db): 

528 user1, token1 = generate_user() 

529 user2, token2 = generate_user() 

530 

531 # send friend request from user1 to user2 

532 with api_session(token1) as api: 

533 api.SendFriendRequest(api_pb2.SendFriendRequestReq(user_id=user2.id)) 

534 

535 with api_session(token2) as api: 

536 with pytest.raises(grpc.RpcError) as e: 

537 api.SendFriendRequest(api_pb2.SendFriendRequestReq(user_id=user1.id)) 

538 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

539 assert e.value.details() == errors.FRIENDS_ALREADY_OR_PENDING 

540 

541 

542def test_cant_friend_request_already_friends(db): 

543 user1, token1 = generate_user() 

544 user2, token2 = generate_user() 

545 make_friends(user1, user2) 

546 

547 with api_session(token1) as api: 

548 with pytest.raises(grpc.RpcError) as e: 

549 api.SendFriendRequest(api_pb2.SendFriendRequestReq(user_id=user2.id)) 

550 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

551 assert e.value.details() == errors.FRIENDS_ALREADY_OR_PENDING 

552 

553 with api_session(token2) as api: 

554 with pytest.raises(grpc.RpcError) as e: 

555 api.SendFriendRequest(api_pb2.SendFriendRequestReq(user_id=user1.id)) 

556 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

557 assert e.value.details() == errors.FRIENDS_ALREADY_OR_PENDING 

558 

559 

560def test_ListFriends(db): 

561 user1, token1 = generate_user() 

562 user2, token2 = generate_user() 

563 user3, token3 = generate_user() 

564 

565 # send friend request from user1 to user2 and user3 

566 with api_session(token1) as api: 

567 api.SendFriendRequest(api_pb2.SendFriendRequestReq(user_id=user2.id)) 

568 api.SendFriendRequest(api_pb2.SendFriendRequestReq(user_id=user3.id)) 

569 

570 with api_session(token3) as api: 

571 api.SendFriendRequest(api_pb2.SendFriendRequestReq(user_id=user2.id)) 

572 

573 with api_session(token2) as api: 

574 res = api.ListFriendRequests(empty_pb2.Empty()) 

575 assert len(res.received) == 2 

576 

577 # order is an implementation detail 

578 user1_req = [req for req in res.received if req.user_id == user1.id][0] 

579 user3_req = [req for req in res.received if req.user_id == user3.id][0] 

580 

581 assert user1_req.state == api_pb2.FriendRequest.FriendRequestStatus.PENDING 

582 assert user1_req.user_id == user1.id 

583 api.RespondFriendRequest( 

584 api_pb2.RespondFriendRequestReq(friend_request_id=user1_req.friend_request_id, accept=True) 

585 ) 

586 

587 assert user3_req.state == api_pb2.FriendRequest.FriendRequestStatus.PENDING 

588 assert user3_req.user_id == user3.id 

589 api.RespondFriendRequest( 

590 api_pb2.RespondFriendRequestReq(friend_request_id=user3_req.friend_request_id, accept=True) 

591 ) 

592 

593 # check we now have two friends 

594 res = api.ListFriends(empty_pb2.Empty()) 

595 assert len(res.user_ids) == 2 

596 assert user1.id in res.user_ids 

597 assert user3.id in res.user_ids 

598 

599 with api_session(token3) as api: 

600 res = api.ListFriends(empty_pb2.Empty()) 

601 assert len(res.user_ids) == 1 

602 assert user2.id in res.user_ids 

603 

604 res = api.ListFriendRequests(empty_pb2.Empty()) 

605 assert len(res.received) == 1 

606 assert res.received[0].state == api_pb2.FriendRequest.FriendRequestStatus.PENDING 

607 assert res.received[0].user_id == user1.id 

608 fr_id = res.received[0].friend_request_id 

609 api.RespondFriendRequest(api_pb2.RespondFriendRequestReq(friend_request_id=fr_id, accept=True)) 

610 

611 res = api.ListFriends(empty_pb2.Empty()) 

612 assert len(res.user_ids) == 2 

613 assert user1.id in res.user_ids 

614 assert user2.id in res.user_ids 

615 

616 with api_session(token1) as api: 

617 res = api.ListFriends(empty_pb2.Empty()) 

618 assert len(res.user_ids) == 2 

619 assert user2.id in res.user_ids 

620 assert user3.id in res.user_ids 

621 

622 

623def test_ListMutualFriends(db): 

624 user1, token1 = generate_user() 

625 user2, token2 = generate_user() 

626 user3, token3 = generate_user() 

627 user4, token4 = generate_user() 

628 user5, token5 = generate_user() 

629 

630 # arrange friends like this: 1<->2, 1<->3, 1<->4, 1<->5, 3<->2, 3<->4, 

631 # so 1 and 2 should have mutual friend 3 only 

632 make_friends(user1, user2) 

633 make_friends(user1, user3) 

634 make_friends(user1, user4) 

635 make_friends(user1, user5) 

636 make_friends(user3, user2) 

637 make_friends(user3, user4) 

638 

639 with api_session(token1) as api: 

640 mutual_friends = api.ListMutualFriends(api_pb2.ListMutualFriendsReq(user_id=user2.id)).mutual_friends 

641 assert len(mutual_friends) == 1 

642 assert mutual_friends[0].user_id == user3.id 

643 

644 # and other way around same 

645 with api_session(token2) as api: 

646 mutual_friends = api.ListMutualFriends(api_pb2.ListMutualFriendsReq(user_id=user1.id)).mutual_friends 

647 assert len(mutual_friends) == 1 

648 assert mutual_friends[0].user_id == user3.id 

649 

650 # Check pending request doesn't have effect 

651 api.SendFriendRequest(api_pb2.SendFriendRequestReq(user_id=user5.id)) 

652 

653 mutual_friends = api.ListMutualFriends(api_pb2.ListMutualFriendsReq(user_id=user1.id)).mutual_friends 

654 assert len(mutual_friends) == 1 

655 assert mutual_friends[0].user_id == user3.id 

656 

657 # both ways 

658 with api_session(token1) as api: 

659 mutual_friends = api.ListMutualFriends(api_pb2.ListMutualFriendsReq(user_id=user2.id)).mutual_friends 

660 assert len(mutual_friends) == 1 

661 assert mutual_friends[0].user_id == user3.id 

662 

663 

664def test_mutual_friends_self(db): 

665 user1, token1 = generate_user() 

666 user2, token2 = generate_user() 

667 user3, token3 = generate_user() 

668 user4, token4 = generate_user() 

669 

670 make_friends(user1, user2) 

671 make_friends(user2, user3) 

672 make_friends(user1, user4) 

673 

674 with api_session(token1) as api: 

675 res = api.ListMutualFriends(api_pb2.ListMutualFriendsReq(user_id=user1.id)) 

676 assert len(res.mutual_friends) == 0 

677 

678 with api_session(token2) as api: 

679 res = api.ListMutualFriends(api_pb2.ListMutualFriendsReq(user_id=user2.id)) 

680 assert len(res.mutual_friends) == 0 

681 

682 with api_session(token3) as api: 

683 res = api.ListMutualFriends(api_pb2.ListMutualFriendsReq(user_id=user3.id)) 

684 assert len(res.mutual_friends) == 0 

685 

686 with api_session(token4) as api: 

687 res = api.ListMutualFriends(api_pb2.ListMutualFriendsReq(user_id=user4.id)) 

688 assert len(res.mutual_friends) == 0 

689 

690 

691def test_CancelFriendRequest(db): 

692 user1, token1 = generate_user() 

693 user2, token2 = generate_user() 

694 

695 with api_session(token1) as api: 

696 api.SendFriendRequest(api_pb2.SendFriendRequestReq(user_id=user2.id)) 

697 

698 res = api.ListFriendRequests(empty_pb2.Empty()) 

699 assert res.sent[0].user_id == user2.id 

700 fr_id = res.sent[0].friend_request_id 

701 

702 api.CancelFriendRequest(api_pb2.CancelFriendRequestReq(friend_request_id=fr_id)) 

703 

704 # check it's gone 

705 res = api.ListFriendRequests(empty_pb2.Empty()) 

706 assert len(res.sent) == 0 

707 assert len(res.received) == 0 

708 

709 # check not friends 

710 res = api.ListFriends(empty_pb2.Empty()) 

711 assert len(res.user_ids) == 0 

712 

713 with api_session(token2) as api: 

714 # check it's gone 

715 res = api.ListFriendRequests(empty_pb2.Empty()) 

716 assert len(res.sent) == 0 

717 assert len(res.received) == 0 

718 

719 # check we're not friends 

720 res = api.ListFriends(empty_pb2.Empty()) 

721 assert len(res.user_ids) == 0 

722 

723 with api_session(token1) as api: 

724 # check we can send another friend req 

725 api.SendFriendRequest(api_pb2.SendFriendRequestReq(user_id=user2.id)) 

726 

727 res = api.ListFriendRequests(empty_pb2.Empty()) 

728 assert res.sent[0].state == api_pb2.FriendRequest.FriendRequestStatus.PENDING 

729 assert res.sent[0].user_id == user2.id 

730 

731 

732def test_accept_friend_request(db): 

733 user1, token1 = generate_user() 

734 user2, token2 = generate_user() 

735 

736 with session_scope() as session: 

737 friend_request = FriendRelationship(from_user_id=user1.id, to_user_id=user2.id, status=FriendStatus.pending) 

738 session.add(friend_request) 

739 session.commit() 

740 friend_request_id = friend_request.id 

741 

742 with api_session(token2) as api: 

743 # check request pending 

744 res = api.ListFriendRequests(empty_pb2.Empty()) 

745 assert len(res.received) == 1 

746 assert res.received[0].user_id == user1.id 

747 

748 api.RespondFriendRequest(api_pb2.RespondFriendRequestReq(friend_request_id=friend_request_id, accept=True)) 

749 

750 # check request is gone 

751 res = api.ListFriendRequests(empty_pb2.Empty()) 

752 assert len(res.sent) == 0 

753 assert len(res.received) == 0 

754 

755 # check now friends 

756 res = api.ListFriends(empty_pb2.Empty()) 

757 assert len(res.user_ids) == 1 

758 assert res.user_ids[0] == user1.id 

759 

760 with api_session(token1) as api: 

761 # check request gone 

762 res = api.ListFriendRequests(empty_pb2.Empty()) 

763 assert len(res.sent) == 0 

764 assert len(res.received) == 0 

765 

766 # check now friends 

767 res = api.ListFriends(empty_pb2.Empty()) 

768 assert len(res.user_ids) == 1 

769 assert res.user_ids[0] == user2.id 

770 

771 

772def test_reject_friend_request(db): 

773 user1, token1 = generate_user() 

774 user2, token2 = generate_user() 

775 

776 with api_session(token1) as api: 

777 api.SendFriendRequest(api_pb2.SendFriendRequestReq(user_id=user2.id)) 

778 

779 res = api.ListFriendRequests(empty_pb2.Empty()) 

780 assert res.sent[0].state == api_pb2.FriendRequest.FriendRequestStatus.PENDING 

781 assert res.sent[0].user_id == user2.id 

782 

783 with api_session(token2) as api: 

784 res = api.ListFriendRequests(empty_pb2.Empty()) 

785 assert res.received[0].state == api_pb2.FriendRequest.FriendRequestStatus.PENDING 

786 assert res.received[0].user_id == user1.id 

787 

788 fr_id = res.received[0].friend_request_id 

789 

790 # reject it 

791 api.RespondFriendRequest(api_pb2.RespondFriendRequestReq(friend_request_id=fr_id, accept=False)) 

792 

793 # check it's gone 

794 res = api.ListFriendRequests(empty_pb2.Empty()) 

795 assert len(res.sent) == 0 

796 assert len(res.received) == 0 

797 

798 # check not friends 

799 res = api.ListFriends(empty_pb2.Empty()) 

800 assert len(res.user_ids) == 0 

801 

802 with api_session(token1) as api: 

803 # check it's gone 

804 res = api.ListFriendRequests(empty_pb2.Empty()) 

805 assert len(res.sent) == 0 

806 assert len(res.received) == 0 

807 

808 # check we're not friends 

809 res = api.ListFriends(empty_pb2.Empty()) 

810 assert len(res.user_ids) == 0 

811 

812 # check we can send another friend req 

813 api.SendFriendRequest(api_pb2.SendFriendRequestReq(user_id=user2.id)) 

814 

815 res = api.ListFriendRequests(empty_pb2.Empty()) 

816 assert res.sent[0].state == api_pb2.FriendRequest.FriendRequestStatus.PENDING 

817 assert res.sent[0].user_id == user2.id 

818 

819 

820def test_hosting_preferences(db): 

821 user1, token1 = generate_user() 

822 user2, token2 = generate_user() 

823 

824 with api_session(token1) as api: 

825 res = api.GetUser(api_pb2.GetUserReq(user=user1.username)) 

826 assert not res.HasField("max_guests") 

827 assert not res.HasField("last_minute") 

828 assert not res.HasField("has_pets") 

829 assert not res.HasField("accepts_pets") 

830 assert not res.HasField("pet_details") 

831 assert not res.HasField("has_kids") 

832 assert not res.HasField("accepts_kids") 

833 assert not res.HasField("kid_details") 

834 assert not res.HasField("has_housemates") 

835 assert not res.HasField("housemate_details") 

836 assert not res.HasField("wheelchair_accessible") 

837 assert res.smoking_allowed == api_pb2.SMOKING_LOCATION_UNKNOWN 

838 assert not res.HasField("smokes_at_home") 

839 assert not res.HasField("drinking_allowed") 

840 assert not res.HasField("drinks_at_home") 

841 assert not res.HasField("other_host_info") 

842 assert res.sleeping_arrangement == api_pb2.SLEEPING_ARRANGEMENT_UNKNOWN 

843 assert not res.HasField("sleeping_details") 

844 assert not res.HasField("area") 

845 assert not res.HasField("house_rules") 

846 assert not res.HasField("parking") 

847 assert res.parking_details == api_pb2.PARKING_DETAILS_UNKNOWN 

848 assert not res.HasField("camping_ok") 

849 

850 api.UpdateProfile( 

851 api_pb2.UpdateProfileReq( 

852 max_guests=api_pb2.NullableUInt32Value(value=3), 

853 last_minute=api_pb2.NullableBoolValue(value=True), 

854 has_pets=api_pb2.NullableBoolValue(value=False), 

855 accepts_pets=api_pb2.NullableBoolValue(value=True), 

856 pet_details=api_pb2.NullableStringValue(value="I love dogs"), 

857 has_kids=api_pb2.NullableBoolValue(value=False), 

858 accepts_kids=api_pb2.NullableBoolValue(value=True), 

859 kid_details=api_pb2.NullableStringValue(value="I hate kids"), 

860 has_housemates=api_pb2.NullableBoolValue(value=False), 

861 housemate_details=api_pb2.NullableStringValue(value="I have 7 housemates"), 

862 wheelchair_accessible=api_pb2.NullableBoolValue(value=True), 

863 smoking_allowed=api_pb2.SMOKING_LOCATION_WINDOW, 

864 area=api_pb2.NullableStringValue(value="area!"), 

865 smokes_at_home=api_pb2.NullableBoolValue(value=False), 

866 drinking_allowed=api_pb2.NullableBoolValue(value=True), 

867 drinks_at_home=api_pb2.NullableBoolValue(value=False), 

868 other_host_info=api_pb2.NullableStringValue(value="I'm pretty swell"), 

869 sleeping_arrangement=api_pb2.SLEEPING_ARRANGEMENT_COMMON, 

870 sleeping_details=api_pb2.NullableStringValue(value="Couch in living room"), 

871 house_rules=api_pb2.NullableStringValue(value="RULES!"), 

872 parking=api_pb2.NullableBoolValue(value=True), 

873 parking_details=api_pb2.PARKING_DETAILS_PAID_ONSITE, 

874 camping_ok=api_pb2.NullableBoolValue(value=False), 

875 ) 

876 ) 

877 

878 # Use a second user to view the hosting preferences just to check 

879 # that it is public information. 

880 with api_session(token2) as api: 

881 res = api.GetUser(api_pb2.GetUserReq(user=user1.username)) 

882 assert res.max_guests.value == 3 

883 assert res.last_minute.value 

884 assert not res.has_pets.value 

885 assert res.accepts_pets.value 

886 assert res.pet_details.value == "I love dogs" 

887 assert not res.has_kids.value 

888 assert res.accepts_kids.value 

889 assert res.kid_details.value == "I hate kids" 

890 assert not res.has_housemates.value 

891 assert res.housemate_details.value == "I have 7 housemates" 

892 assert res.wheelchair_accessible.value 

893 assert res.smoking_allowed == api_pb2.SMOKING_LOCATION_WINDOW 

894 assert not res.smokes_at_home.value 

895 assert res.drinking_allowed.value 

896 assert not res.drinks_at_home.value 

897 assert res.other_host_info.value == "I'm pretty swell" 

898 assert res.sleeping_arrangement == api_pb2.SLEEPING_ARRANGEMENT_COMMON 

899 assert res.sleeping_details.value == "Couch in living room" 

900 assert res.area.value == "area!" 

901 assert res.house_rules.value == "RULES!" 

902 assert res.parking.value 

903 assert res.parking_details == api_pb2.PARKING_DETAILS_PAID_ONSITE 

904 assert not res.camping_ok.value 

905 

906 # test unsetting 

907 with api_session(token1) as api: 

908 api.UpdateProfile( 

909 api_pb2.UpdateProfileReq( 

910 max_guests=api_pb2.NullableUInt32Value(is_null=True), 

911 last_minute=api_pb2.NullableBoolValue(is_null=True), 

912 has_pets=api_pb2.NullableBoolValue(is_null=True), 

913 accepts_pets=api_pb2.NullableBoolValue(is_null=True), 

914 pet_details=api_pb2.NullableStringValue(is_null=True), 

915 has_kids=api_pb2.NullableBoolValue(is_null=True), 

916 accepts_kids=api_pb2.NullableBoolValue(is_null=True), 

917 kid_details=api_pb2.NullableStringValue(is_null=True), 

918 has_housemates=api_pb2.NullableBoolValue(is_null=True), 

919 housemate_details=api_pb2.NullableStringValue(is_null=True), 

920 wheelchair_accessible=api_pb2.NullableBoolValue(is_null=True), 

921 smoking_allowed=api_pb2.SMOKING_LOCATION_UNKNOWN, 

922 area=api_pb2.NullableStringValue(is_null=True), 

923 smokes_at_home=api_pb2.NullableBoolValue(is_null=True), 

924 drinking_allowed=api_pb2.NullableBoolValue(is_null=True), 

925 drinks_at_home=api_pb2.NullableBoolValue(is_null=True), 

926 other_host_info=api_pb2.NullableStringValue(is_null=True), 

927 sleeping_arrangement=api_pb2.SLEEPING_ARRANGEMENT_UNKNOWN, 

928 sleeping_details=api_pb2.NullableStringValue(is_null=True), 

929 house_rules=api_pb2.NullableStringValue(is_null=True), 

930 parking=api_pb2.NullableBoolValue(is_null=True), 

931 parking_details=api_pb2.PARKING_DETAILS_UNKNOWN, 

932 camping_ok=api_pb2.NullableBoolValue(is_null=True), 

933 ) 

934 ) 

935 

936 res = api.GetUser(api_pb2.GetUserReq(user=user1.username)) 

937 assert not res.HasField("max_guests") 

938 assert not res.HasField("last_minute") 

939 assert not res.HasField("has_pets") 

940 assert not res.HasField("accepts_pets") 

941 assert not res.HasField("pet_details") 

942 assert not res.HasField("has_kids") 

943 assert not res.HasField("accepts_kids") 

944 assert not res.HasField("kid_details") 

945 assert not res.HasField("has_housemates") 

946 assert not res.HasField("housemate_details") 

947 assert not res.HasField("wheelchair_accessible") 

948 assert res.smoking_allowed == api_pb2.SMOKING_LOCATION_UNKNOWN 

949 assert not res.HasField("smokes_at_home") 

950 assert not res.HasField("drinking_allowed") 

951 assert not res.HasField("drinks_at_home") 

952 assert not res.HasField("other_host_info") 

953 assert res.sleeping_arrangement == api_pb2.SLEEPING_ARRANGEMENT_UNKNOWN 

954 assert not res.HasField("sleeping_details") 

955 assert not res.HasField("area") 

956 assert not res.HasField("house_rules") 

957 assert not res.HasField("parking") 

958 assert res.parking_details == api_pb2.PARKING_DETAILS_UNKNOWN 

959 assert not res.HasField("camping_ok")