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

741 statements  

« prev     ^ index     » next       coverage.py v7.6.10, created at 2025-06-01 15:07 +0000

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.jobs.handlers import update_badges 

10from couchers.materialized_views import refresh_materialized_views_rapid 

11from couchers.models import FriendRelationship, FriendStatus 

12from couchers.resources import get_badge_dict 

13from couchers.sql import couchers_select as select 

14from couchers.utils import create_coordinate, to_aware_datetime 

15from proto import api_pb2, jail_pb2, notifications_pb2 

16from tests.test_fixtures import ( # noqa 

17 api_session, 

18 blocking_session, 

19 db, 

20 email_fields, 

21 generate_user, 

22 make_friends, 

23 make_user_block, 

24 make_user_invisible, 

25 mock_notification_email, 

26 notifications_session, 

27 push_collector, 

28 real_api_session, 

29 real_jail_session, 

30 testconfig, 

31) 

32 

33 

34@pytest.fixture(autouse=True) 

35def _(testconfig): 

36 pass 

37 

38 

39def test_ping(db): 

40 user, token = generate_user() 

41 

42 with real_api_session(token) as api: 

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

44 

45 assert res.user.user_id == user.id 

46 assert res.user.username == user.username 

47 assert res.user.name == user.name 

48 assert res.user.city == user.city 

49 assert res.user.hometown == user.hometown 

50 assert res.user.verification == 0.0 

51 assert res.user.community_standing == user.community_standing 

52 assert res.user.num_references == 0 

53 assert res.user.gender == user.gender 

54 assert res.user.pronouns == user.pronouns 

55 assert res.user.age == user.age 

56 

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

58 

59 # the joined time is fuzzed 

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

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

62 # same for last_active 

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

64 

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

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

67 

68 assert res.user.occupation == user.occupation 

69 assert res.user.education == user.education 

70 assert res.user.about_me == user.about_me 

71 assert res.user.things_i_like == user.things_i_like 

72 assert {language_ability.code for language_ability in res.user.language_abilities} == {"fin", "fra"} 

73 assert res.user.about_place == user.about_place 

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

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

76 assert res.user.additional_information == user.additional_information 

77 

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

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

80 

81 

82def test_coords(db): 

83 # make them need to update location 

84 user1, token1 = generate_user(geom=create_coordinate(1, 0), geom_radius=2000, needs_to_update_location=True) 

85 user2, token2 = generate_user() 

86 

87 with api_session(token2) as api: 

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

89 assert res.user.city == user2.city 

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

91 assert res.user.lat == lat 

92 assert res.user.lng == lng 

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

94 

95 with api_session(token2) as api: 

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

97 assert res.city == user1.city 

98 assert res.lat == 1.0 

99 assert res.lng == 0.0 

100 assert res.radius == 2000.0 

101 

102 # Check coordinate wrapping 

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

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

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

106 

107 with api_session(token3) as api: 

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

109 assert res.lat == 40.0 

110 assert res.lng == 179.5 

111 

112 with api_session(token4) as api: 

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

114 assert res.lat == 40.0 

115 assert res.lng == 20.0 

116 

117 # PostGIS does not wrap longitude for latitude overflow 

118 with api_session(token5) as api: 

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

120 assert res.lat == 89.5 

121 assert res.lng == 20.0 

122 

123 with real_jail_session(token1) as jail: 

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

125 assert res.jailed 

126 assert res.needs_to_update_location 

127 

128 res = jail.SetLocation( 

129 jail_pb2.SetLocationReq( 

130 city="New York City", 

131 lat=40.7812, 

132 lng=-73.9647, 

133 radius=250, 

134 ) 

135 ) 

136 

137 assert not res.jailed 

138 assert not res.needs_to_update_location 

139 

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

141 assert not res.jailed 

142 assert not res.needs_to_update_location 

143 

144 with api_session(token2) as api: 

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

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

147 assert res.lat == 40.7812 

148 assert res.lng == -73.9647 

149 assert res.radius == 250 

150 

151 

152def test_get_user(db): 

153 user1, token1 = generate_user() 

154 user2, token2 = generate_user() 

155 

156 with api_session(token1) as api: 

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

158 assert res.user_id == user2.id 

159 assert res.username == user2.username 

160 assert res.name == user2.name 

161 

162 with api_session(token1) as api: 

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

164 assert res.user_id == user2.id 

165 assert res.username == user2.username 

166 assert res.name == user2.name 

167 

168 

169def test_lite_coords(db): 

170 # make them need to update location 

171 user1, token1 = generate_user(geom=create_coordinate(0, 0), geom_radius=0, needs_to_update_location=True) 

172 user2, token2 = generate_user() 

173 

174 refresh_materialized_views_rapid(None) 

175 

176 with api_session(token2) as api: 

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

178 assert res.user.city == user2.city 

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

180 assert res.user.lat == lat 

181 assert res.user.lng == lng 

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

183 

184 with api_session(token2) as api: 

185 res = api.GetLiteUser(api_pb2.GetLiteUserReq(user=user1.username)) 

186 assert res.city == user1.city 

187 assert res.lat == 0.0 

188 assert res.lng == 0.0 

189 assert res.radius == 0.0 

190 

191 # Check coordinate wrapping 

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

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

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

195 

196 refresh_materialized_views_rapid(None) 

197 

198 with api_session(token3) as api: 

199 res = api.GetLiteUser(api_pb2.GetLiteUserReq(user=user3.username)) 

200 assert res.lat == 40.0 

201 assert res.lng == 179.5 

202 

203 with api_session(token4) as api: 

204 res = api.GetLiteUser(api_pb2.GetLiteUserReq(user=user4.username)) 

205 assert res.lat == 40.0 

206 assert res.lng == 20.0 

207 

208 # PostGIS does not wrap longitude for latitude overflow 

209 with api_session(token5) as api: 

210 res = api.GetLiteUser(api_pb2.GetLiteUserReq(user=user5.username)) 

211 assert res.lat == 89.5 

212 assert res.lng == 20.0 

213 

214 with real_jail_session(token1) as jail: 

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

216 assert res.jailed 

217 assert res.needs_to_update_location 

218 

219 res = jail.SetLocation( 

220 jail_pb2.SetLocationReq( 

221 city="New York City", 

222 lat=40.7812, 

223 lng=-73.9647, 

224 radius=250, 

225 ) 

226 ) 

227 

228 assert not res.jailed 

229 assert not res.needs_to_update_location 

230 

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

232 assert not res.jailed 

233 assert not res.needs_to_update_location 

234 

235 refresh_materialized_views_rapid(None) 

236 

237 with api_session(token2) as api: 

238 res = api.GetLiteUser(api_pb2.GetLiteUserReq(user=user1.username)) 

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

240 assert res.lat == 40.7812 

241 assert res.lng == -73.9647 

242 assert res.radius == 250 

243 

244 

245def test_lite_get_user(db): 

246 user1, token1 = generate_user() 

247 user2, token2 = generate_user() 

248 

249 refresh_materialized_views_rapid(None) 

250 

251 with api_session(token1) as api: 

252 res = api.GetLiteUser(api_pb2.GetLiteUserReq(user=user2.username)) 

253 assert res.user_id == user2.id 

254 assert res.username == user2.username 

255 assert res.name == user2.name 

256 

257 with api_session(token1) as api: 

258 res = api.GetLiteUser(api_pb2.GetLiteUserReq(user=str(user2.id))) 

259 assert res.user_id == user2.id 

260 assert res.username == user2.username 

261 assert res.name == user2.name 

262 

263 

264def test_GetLiteUsers(db): 

265 user1, token1 = generate_user() 

266 user2, _ = generate_user() 

267 user3, _ = generate_user() 

268 user4, _ = generate_user() 

269 user5, _ = generate_user() 

270 user6, _ = generate_user() 

271 

272 make_user_block(user4, user1) 

273 

274 refresh_materialized_views_rapid(None) 

275 

276 with api_session(token1) as api: 

277 res = api.GetLiteUsers( 

278 api_pb2.GetLiteUsersReq( 

279 users=[ 

280 user1.username, 

281 str(user1.id), 

282 "nonexistent", 

283 str(user2.id), 

284 "9994", 

285 user6.username, 

286 str(user5.id), 

287 "notreal", 

288 user4.username, 

289 ] 

290 ) 

291 ) 

292 

293 assert len(res.responses) == 9 

294 assert res.responses[0].query == user1.username 

295 assert res.responses[0].user.user_id == user1.id 

296 

297 assert res.responses[1].query == str(user1.id) 

298 assert res.responses[1].user.user_id == user1.id 

299 

300 assert res.responses[2].query == "nonexistent" 

301 assert res.responses[2].not_found 

302 

303 assert res.responses[3].query == str(user2.id) 

304 assert res.responses[3].user.user_id == user2.id 

305 

306 assert res.responses[4].query == "9994" 

307 assert res.responses[4].not_found 

308 

309 assert res.responses[5].query == user6.username 

310 assert res.responses[5].user.user_id == user6.id 

311 

312 assert res.responses[6].query == str(user5.id) 

313 assert res.responses[6].user.user_id == user5.id 

314 

315 assert res.responses[7].query == "notreal" 

316 assert res.responses[7].not_found 

317 

318 # blocked 

319 assert res.responses[8].query == user4.username 

320 assert res.responses[8].not_found 

321 

322 with api_session(token1) as api: 

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

324 api.GetLiteUsers(api_pb2.GetLiteUsersReq(users=201 * [user1.username])) 

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

326 assert e.value.details() == errors.REQUESTED_TOO_MANY_USERS 

327 

328 

329def test_update_profile(db): 

330 user, token = generate_user() 

331 

332 with api_session(token) as api: 

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

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

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

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

337 

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

339 api.UpdateProfile( 

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

341 ) 

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

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

344 

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

346 api.UpdateProfile( 

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

348 ) 

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

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

351 

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

353 api.UpdateProfile( 

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

355 ) 

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

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

358 

359 api.UpdateProfile( 

360 api_pb2.UpdateProfileReq( 

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

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

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

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

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

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

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

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

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

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

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

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

373 hosting_status=api_pb2.HOSTING_STATUS_CAN_HOST, 

374 meetup_status=api_pb2.MEETUP_STATUS_WANTS_TO_MEETUP, 

375 language_abilities=api_pb2.RepeatedLanguageAbilityValue( 

376 value=[ 

377 api_pb2.LanguageAbility( 

378 code="eng", 

379 fluency=api_pb2.LanguageAbility.Fluency.FLUENCY_FLUENT, 

380 ) 

381 ], 

382 ), 

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

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

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

386 ) 

387 ) 

388 

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

390 assert user_details.name == "New name" 

391 assert user_details.city == "Timbuktu" 

392 assert user_details.hometown == "Walla Walla" 

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

394 assert user_details.education == "Couchers U" 

395 assert user_details.things_i_like == "Couchers" 

396 assert user_details.lat == 0.01 

397 assert user_details.lng == -2 

398 assert user_details.radius == 321 

399 assert user_details.occupation == "Testing" 

400 assert user_details.about_me == "I rule" 

401 assert user_details.about_place == "My place" 

402 assert user_details.hosting_status == api_pb2.HOSTING_STATUS_CAN_HOST 

403 assert user_details.meetup_status == api_pb2.MEETUP_STATUS_WANTS_TO_MEETUP 

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

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

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

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

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

409 

410 # Test unset values 

411 api.UpdateProfile( 

412 api_pb2.UpdateProfileReq( 

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

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

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

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

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

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

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

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

421 hosting_status=api_pb2.HOSTING_STATUS_CAN_HOST, 

422 meetup_status=api_pb2.MEETUP_STATUS_WANTS_TO_MEETUP, 

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

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

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

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

427 ) 

428 ) 

429 

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

431 assert not user_details.hometown 

432 assert not user_details.radius 

433 assert not user_details.pronouns 

434 assert not user_details.occupation 

435 assert not user_details.education 

436 assert not user_details.about_me 

437 assert not user_details.things_i_like 

438 assert not user_details.about_place 

439 assert user_details.hosting_status == api_pb2.HOSTING_STATUS_CAN_HOST 

440 assert user_details.meetup_status == api_pb2.MEETUP_STATUS_WANTS_TO_MEETUP 

441 assert not user_details.language_abilities 

442 assert not user_details.regions_visited 

443 assert not user_details.regions_lived 

444 assert not user_details.additional_information 

445 

446 

447def test_update_profile_do_not_email(db): 

448 user, token = generate_user() 

449 

450 with notifications_session(token) as notifications: 

451 notifications.SetNotificationSettings(notifications_pb2.SetNotificationSettingsReq(enable_do_not_email=True)) 

452 

453 with api_session(token) as api: 

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

455 api.UpdateProfile(api_pb2.UpdateProfileReq(hosting_status=api_pb2.HOSTING_STATUS_CAN_HOST)) 

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

457 assert e.value.details() == errors.DO_NOT_EMAIL_CANNOT_HOST 

458 

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

460 api.UpdateProfile(api_pb2.UpdateProfileReq(meetup_status=api_pb2.MEETUP_STATUS_OPEN_TO_MEETUP)) 

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

462 assert e.value.details() == errors.DO_NOT_EMAIL_CANNOT_MEET 

463 

464 

465def test_language_abilities(db): 

466 user, token = generate_user() 

467 

468 with api_session(token) as api: 

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

470 assert len(res.language_abilities) == 2 

471 

472 # can't add non-existent languages 

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

474 res = api.UpdateProfile( 

475 api_pb2.UpdateProfileReq( 

476 language_abilities=api_pb2.RepeatedLanguageAbilityValue( 

477 value=[ 

478 api_pb2.LanguageAbility( 

479 code="QQQ", 

480 fluency=api_pb2.LanguageAbility.Fluency.FLUENCY_FLUENT, 

481 ) 

482 ], 

483 ), 

484 ) 

485 ) 

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

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

488 

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

490 with pytest.raises(Exception) as e: 

491 res = api.UpdateProfile( 

492 api_pb2.UpdateProfileReq( 

493 language_abilities=api_pb2.RepeatedLanguageAbilityValue( 

494 value=[ 

495 api_pb2.LanguageAbility( 

496 code="eng", 

497 fluency=api_pb2.LanguageAbility.Fluency.FLUENCY_FLUENT, 

498 ), 

499 api_pb2.LanguageAbility( 

500 code="eng", 

501 fluency=api_pb2.LanguageAbility.Fluency.FLUENCY_FLUENT, 

502 ), 

503 ], 

504 ), 

505 ) 

506 ) 

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

508 

509 # nothing changed 

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

511 assert len(res.language_abilities) == 2 

512 

513 # now actually add a value 

514 api.UpdateProfile( 

515 api_pb2.UpdateProfileReq( 

516 language_abilities=api_pb2.RepeatedLanguageAbilityValue( 

517 value=[ 

518 api_pb2.LanguageAbility( 

519 code="eng", 

520 fluency=api_pb2.LanguageAbility.Fluency.FLUENCY_FLUENT, 

521 ) 

522 ], 

523 ), 

524 ) 

525 ) 

526 

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

528 assert len(res.language_abilities) == 1 

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

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

531 

532 # change the value to a new one 

533 api.UpdateProfile( 

534 api_pb2.UpdateProfileReq( 

535 language_abilities=api_pb2.RepeatedLanguageAbilityValue( 

536 value=[ 

537 api_pb2.LanguageAbility( 

538 code="fin", 

539 fluency=api_pb2.LanguageAbility.Fluency.FLUENCY_BEGINNER, 

540 ) 

541 ], 

542 ), 

543 ) 

544 ) 

545 

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

547 assert len(res.language_abilities) == 1 

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

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

550 

551 # should be able to set to same value still 

552 api.UpdateProfile( 

553 api_pb2.UpdateProfileReq( 

554 language_abilities=api_pb2.RepeatedLanguageAbilityValue( 

555 value=[ 

556 api_pb2.LanguageAbility( 

557 code="fin", 

558 fluency=api_pb2.LanguageAbility.Fluency.FLUENCY_BEGINNER, 

559 ) 

560 ], 

561 ), 

562 ) 

563 ) 

564 

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

566 assert len(res.language_abilities) == 1 

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

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

569 

570 # don't change it 

571 api.UpdateProfile(api_pb2.UpdateProfileReq()) 

572 

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

574 assert len(res.language_abilities) == 1 

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

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

577 

578 # remove value 

579 api.UpdateProfile( 

580 api_pb2.UpdateProfileReq( 

581 language_abilities=api_pb2.RepeatedLanguageAbilityValue( 

582 value=[], 

583 ), 

584 ) 

585 ) 

586 

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

588 assert len(res.language_abilities) == 0 

589 

590 

591def test_pending_friend_request_count(db): 

592 user1, token1 = generate_user() 

593 user2, token2 = generate_user() 

594 user3, token3 = generate_user() 

595 

596 with api_session(token2) as api: 

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

598 assert res.pending_friend_request_count == 0 

599 

600 with api_session(token1) as api: 

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

602 assert res.pending_friend_request_count == 0 

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

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

605 assert res.pending_friend_request_count == 0 

606 

607 with api_session(token2) as api: 

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

609 assert res.pending_friend_request_count == 1 

610 

611 with api_session(token2) as api: 

612 # check it's there 

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

614 assert len(res.sent) == 0 

615 assert len(res.received) == 1 

616 

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

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

619 

620 fr_id = res.received[0].friend_request_id 

621 

622 # accept it 

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

624 

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

626 assert res.pending_friend_request_count == 0 

627 

628 

629def test_friend_request_flow(db, push_collector): 

630 user1, token1 = generate_user(complete_profile=True) 

631 user2, token2 = generate_user(complete_profile=True) 

632 user3, token3 = generate_user() 

633 

634 # send friend request from user1 to user2 

635 with mock_notification_email() as mock: 

636 with api_session(token1) as api: 

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

638 

639 push_collector.assert_user_has_single_matching( 

640 user2.id, 

641 title=f"{user1.name} wants to be your friend", 

642 body=f"You've received a friend request from {user1.name}", 

643 ) 

644 

645 mock.assert_called_once() 

646 e = email_fields(mock) 

647 assert e.recipient == user2.email 

648 assert e.subject == f"[TEST] {user1.name} wants to be your friend on Couchers.org!" 

649 assert user2.name in e.plain 

650 assert user2.name in e.html 

651 assert user1.name in e.plain 

652 assert user1.name in e.html 

653 assert "http://localhost:5001/img/thumbnail/" not in e.plain 

654 assert "http://localhost:5001/img/thumbnail/" in e.html 

655 assert "http://localhost:3000/connections/friends/" in e.plain 

656 assert "http://localhost:3000/connections/friends/" in e.html 

657 

658 with session_scope() as session: 

659 friend_request_id = ( 

660 session.execute( 

661 select(FriendRelationship).where( 

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

663 ) 

664 ).scalar_one_or_none() 

665 ).id 

666 

667 with api_session(token1) as api: 

668 # check it went through 

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

670 assert len(res.sent) == 1 

671 assert len(res.received) == 0 

672 

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

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

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

676 

677 with api_session(token2) as api: 

678 # check it's there 

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

680 assert len(res.sent) == 0 

681 assert len(res.received) == 1 

682 

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

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

685 

686 fr_id = res.received[0].friend_request_id 

687 

688 # accept it 

689 with mock_notification_email() as mock: 

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

691 

692 # check it's gone 

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

694 assert len(res.sent) == 0 

695 assert len(res.received) == 0 

696 

697 # check we're friends now 

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

699 assert len(res.user_ids) == 1 

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

701 

702 push_collector.assert_user_has_count(user2.id, 1) 

703 push_collector.assert_user_push_matches_fields( 

704 user1.id, 

705 title=f"{user2.name} accepted your friend request!", 

706 body=f"{user2.name} has accepted your friend request", 

707 ) 

708 

709 mock.assert_called_once() 

710 e = email_fields(mock) 

711 assert e.recipient == user1.email 

712 assert e.subject == f"[TEST] {user2.name} accepted your friend request!" 

713 assert user1.name in e.plain 

714 assert user1.name in e.html 

715 assert user2.name in e.plain 

716 assert user2.name in e.html 

717 assert "http://localhost:5001/img/thumbnail/" not in e.plain 

718 assert "http://localhost:5001/img/thumbnail/" in e.html 

719 assert f"http://localhost:3000/user/{user2.username}" in e.plain 

720 assert f"http://localhost:3000/user/{user2.username}" in e.html 

721 

722 with api_session(token1) as api: 

723 # check it's gone 

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

725 assert len(res.sent) == 0 

726 assert len(res.received) == 0 

727 

728 # check we're friends now 

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

730 assert len(res.user_ids) == 1 

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

732 

733 with api_session(token1) as api: 

734 # we can't unfriend if we aren't friends 

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

736 api.RemoveFriend(api_pb2.RemoveFriendReq(user_id=user3.id)) 

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

738 assert e.value.details() == errors.NOT_FRIENDS 

739 

740 # we can unfriend 

741 res = api.RemoveFriend(api_pb2.RemoveFriendReq(user_id=user2.id)) 

742 

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

744 assert len(res.user_ids) == 0 

745 

746 

747def test_RemoveFriend_regression(db, push_collector): 

748 user1, token1 = generate_user(complete_profile=True) 

749 user2, token2 = generate_user(complete_profile=True) 

750 user3, token3 = generate_user() 

751 user4, token4 = generate_user() 

752 user5, token5 = generate_user() 

753 user6, token6 = generate_user() 

754 

755 with api_session(token4) as api: 

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

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

758 

759 with api_session(token5) as api: 

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

761 

762 with api_session(token1) as api: 

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

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

765 

766 api.RespondFriendRequest( 

767 api_pb2.RespondFriendRequestReq( 

768 friend_request_id=api.ListFriendRequests(empty_pb2.Empty()).received[0].friend_request_id, accept=True 

769 ) 

770 ) 

771 

772 with api_session(token2) as api: 

773 for fr in api.ListFriendRequests(empty_pb2.Empty()).received: 

774 api.RespondFriendRequest( 

775 api_pb2.RespondFriendRequestReq(friend_request_id=fr.friend_request_id, accept=True) 

776 ) 

777 

778 with api_session(token1) as api: 

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

780 assert sorted(res.user_ids) == [2, 4] 

781 

782 api.RemoveFriend(api_pb2.RemoveFriendReq(user_id=user2.id)) 

783 

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

785 assert sorted(res.user_ids) == [4] 

786 

787 api.RemoveFriend(api_pb2.RemoveFriendReq(user_id=user4.id)) 

788 

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

790 assert not res.user_ids 

791 

792 

793def test_cant_friend_request_twice(db): 

794 user1, token1 = generate_user() 

795 user2, token2 = generate_user() 

796 

797 # send friend request from user1 to user2 

798 with api_session(token1) as api: 

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

800 

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

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

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

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

805 

806 

807def test_cant_friend_request_pending(db): 

808 user1, token1 = generate_user() 

809 user2, token2 = generate_user() 

810 

811 # send friend request from user1 to user2 

812 with api_session(token1) as api: 

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

814 

815 with api_session(token2) as api: 

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

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

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

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

820 

821 

822def test_cant_friend_request_already_friends(db): 

823 user1, token1 = generate_user() 

824 user2, token2 = generate_user() 

825 make_friends(user1, user2) 

826 

827 with api_session(token1) as api: 

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

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

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

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

832 

833 with api_session(token2) as api: 

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

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

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

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

838 

839 

840def test_ListFriends(db): 

841 user1, token1 = generate_user() 

842 user2, token2 = generate_user() 

843 user3, token3 = generate_user() 

844 

845 # send friend request from user1 to user2 and user3 

846 with api_session(token1) as api: 

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

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

849 

850 with api_session(token3) as api: 

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

852 

853 with api_session(token2) as api: 

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

855 assert len(res.received) == 2 

856 

857 # order is an implementation detail 

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

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

860 

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

862 assert user1_req.user_id == user1.id 

863 api.RespondFriendRequest( 

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

865 ) 

866 

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

868 assert user3_req.user_id == user3.id 

869 api.RespondFriendRequest( 

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

871 ) 

872 

873 # check we now have two friends 

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

875 assert len(res.user_ids) == 2 

876 assert user1.id in res.user_ids 

877 assert user3.id in res.user_ids 

878 

879 with api_session(token3) as api: 

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

881 assert len(res.user_ids) == 1 

882 assert user2.id in res.user_ids 

883 

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

885 assert len(res.received) == 1 

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

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

888 fr_id = res.received[0].friend_request_id 

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

890 

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

892 assert len(res.user_ids) == 2 

893 assert user1.id in res.user_ids 

894 assert user2.id in res.user_ids 

895 

896 with api_session(token1) as api: 

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

898 assert len(res.user_ids) == 2 

899 assert user2.id in res.user_ids 

900 assert user3.id in res.user_ids 

901 

902 

903def test_ListMutualFriends(db): 

904 user1, token1 = generate_user() 

905 user2, token2 = generate_user() 

906 user3, token3 = generate_user() 

907 user4, token4 = generate_user() 

908 user5, token5 = generate_user() 

909 

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

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

912 make_friends(user1, user2) 

913 make_friends(user1, user3) 

914 make_friends(user1, user4) 

915 make_friends(user1, user5) 

916 make_friends(user3, user2) 

917 make_friends(user3, user4) 

918 

919 with api_session(token1) as api: 

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

921 assert len(mutual_friends) == 1 

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

923 

924 # and other way around same 

925 with api_session(token2) as api: 

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

927 assert len(mutual_friends) == 1 

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

929 

930 # Check pending request doesn't have effect 

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

932 

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

934 assert len(mutual_friends) == 1 

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

936 

937 # both ways 

938 with api_session(token1) as api: 

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

940 assert len(mutual_friends) == 1 

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

942 

943 

944def test_mutual_friends_self(db): 

945 user1, token1 = generate_user() 

946 user2, token2 = generate_user() 

947 user3, token3 = generate_user() 

948 user4, token4 = generate_user() 

949 

950 make_friends(user1, user2) 

951 make_friends(user2, user3) 

952 make_friends(user1, user4) 

953 

954 with api_session(token1) as api: 

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

956 assert len(res.mutual_friends) == 0 

957 

958 with api_session(token2) as api: 

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

960 assert len(res.mutual_friends) == 0 

961 

962 with api_session(token3) as api: 

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

964 assert len(res.mutual_friends) == 0 

965 

966 with api_session(token4) as api: 

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

968 assert len(res.mutual_friends) == 0 

969 

970 

971def test_CancelFriendRequest(db): 

972 user1, token1 = generate_user() 

973 user2, token2 = generate_user() 

974 

975 with api_session(token1) as api: 

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

977 

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

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

980 fr_id = res.sent[0].friend_request_id 

981 

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

983 

984 # check it's gone 

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

986 assert len(res.sent) == 0 

987 assert len(res.received) == 0 

988 

989 # check not friends 

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

991 assert len(res.user_ids) == 0 

992 

993 with api_session(token2) as api: 

994 # check it's gone 

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

996 assert len(res.sent) == 0 

997 assert len(res.received) == 0 

998 

999 # check we're not friends 

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

1001 assert len(res.user_ids) == 0 

1002 

1003 with api_session(token1) as api: 

1004 # check we can send another friend req 

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

1006 

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

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

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

1010 

1011 

1012def test_accept_friend_request(db): 

1013 user1, token1 = generate_user() 

1014 user2, token2 = generate_user() 

1015 

1016 with session_scope() as session: 

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

1018 session.add(friend_request) 

1019 session.commit() 

1020 friend_request_id = friend_request.id 

1021 

1022 with api_session(token2) as api: 

1023 # check request pending 

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

1025 assert len(res.received) == 1 

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

1027 

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

1029 

1030 # check request is gone 

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

1032 assert len(res.sent) == 0 

1033 assert len(res.received) == 0 

1034 

1035 # check now friends 

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

1037 assert len(res.user_ids) == 1 

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

1039 

1040 with api_session(token1) as api: 

1041 # check request gone 

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

1043 assert len(res.sent) == 0 

1044 assert len(res.received) == 0 

1045 

1046 # check now friends 

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

1048 assert len(res.user_ids) == 1 

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

1050 

1051 

1052def test_reject_friend_request(db): 

1053 user1, token1 = generate_user() 

1054 user2, token2 = generate_user() 

1055 

1056 with api_session(token1) as api: 

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

1058 

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

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

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

1062 

1063 with api_session(token2) as api: 

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

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

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

1067 

1068 fr_id = res.received[0].friend_request_id 

1069 

1070 # reject it 

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

1072 

1073 # check it's gone 

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

1075 assert len(res.sent) == 0 

1076 assert len(res.received) == 0 

1077 

1078 # check not friends 

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

1080 assert len(res.user_ids) == 0 

1081 

1082 with api_session(token1) as api: 

1083 # check it's gone 

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

1085 assert len(res.sent) == 0 

1086 assert len(res.received) == 0 

1087 

1088 # check we're not friends 

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

1090 assert len(res.user_ids) == 0 

1091 

1092 # check we can send another friend req 

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

1094 

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

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

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

1098 

1099 

1100def test_hosting_preferences(db): 

1101 user1, token1 = generate_user() 

1102 user2, token2 = generate_user() 

1103 

1104 with api_session(token1) as api: 

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

1106 assert not res.HasField("max_guests") 

1107 assert not res.HasField("last_minute") 

1108 assert not res.HasField("has_pets") 

1109 assert not res.HasField("accepts_pets") 

1110 assert not res.HasField("pet_details") 

1111 assert not res.HasField("has_kids") 

1112 assert not res.HasField("accepts_kids") 

1113 assert not res.HasField("kid_details") 

1114 assert not res.HasField("has_housemates") 

1115 assert not res.HasField("housemate_details") 

1116 assert not res.HasField("wheelchair_accessible") 

1117 assert res.smoking_allowed == api_pb2.SMOKING_LOCATION_UNKNOWN 

1118 assert not res.HasField("smokes_at_home") 

1119 assert not res.HasField("drinking_allowed") 

1120 assert not res.HasField("drinks_at_home") 

1121 assert not res.HasField("other_host_info") 

1122 assert res.sleeping_arrangement == api_pb2.SLEEPING_ARRANGEMENT_UNKNOWN 

1123 assert not res.HasField("sleeping_details") 

1124 assert not res.HasField("area") 

1125 assert not res.HasField("house_rules") 

1126 assert not res.HasField("parking") 

1127 assert res.parking_details == api_pb2.PARKING_DETAILS_UNKNOWN 

1128 assert not res.HasField("camping_ok") 

1129 

1130 api.UpdateProfile( 

1131 api_pb2.UpdateProfileReq( 

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

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

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

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

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

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

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

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

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

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

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

1143 smoking_allowed=api_pb2.SMOKING_LOCATION_WINDOW, 

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

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

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

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

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

1149 sleeping_arrangement=api_pb2.SLEEPING_ARRANGEMENT_COMMON, 

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

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

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

1153 parking_details=api_pb2.PARKING_DETAILS_PAID_ONSITE, 

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

1155 ) 

1156 ) 

1157 

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

1159 # that it is public information. 

1160 with api_session(token2) as api: 

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

1162 assert res.max_guests.value == 3 

1163 assert res.last_minute.value 

1164 assert not res.has_pets.value 

1165 assert res.accepts_pets.value 

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

1167 assert not res.has_kids.value 

1168 assert res.accepts_kids.value 

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

1170 assert not res.has_housemates.value 

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

1172 assert res.wheelchair_accessible.value 

1173 assert res.smoking_allowed == api_pb2.SMOKING_LOCATION_WINDOW 

1174 assert not res.smokes_at_home.value 

1175 assert res.drinking_allowed.value 

1176 assert not res.drinks_at_home.value 

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

1178 assert res.sleeping_arrangement == api_pb2.SLEEPING_ARRANGEMENT_COMMON 

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

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

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

1182 assert res.parking.value 

1183 assert res.parking_details == api_pb2.PARKING_DETAILS_PAID_ONSITE 

1184 assert not res.camping_ok.value 

1185 

1186 # test unsetting 

1187 with api_session(token1) as api: 

1188 api.UpdateProfile( 

1189 api_pb2.UpdateProfileReq( 

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

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

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

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

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

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

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

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

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

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

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

1201 smoking_allowed=api_pb2.SMOKING_LOCATION_UNKNOWN, 

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

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

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

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

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

1207 sleeping_arrangement=api_pb2.SLEEPING_ARRANGEMENT_UNKNOWN, 

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

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

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

1211 parking_details=api_pb2.PARKING_DETAILS_UNKNOWN, 

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

1213 ) 

1214 ) 

1215 

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

1217 assert not res.HasField("max_guests") 

1218 assert not res.HasField("last_minute") 

1219 assert not res.HasField("has_pets") 

1220 assert not res.HasField("accepts_pets") 

1221 assert not res.HasField("pet_details") 

1222 assert not res.HasField("has_kids") 

1223 assert not res.HasField("accepts_kids") 

1224 assert not res.HasField("kid_details") 

1225 assert not res.HasField("has_housemates") 

1226 assert not res.HasField("housemate_details") 

1227 assert not res.HasField("wheelchair_accessible") 

1228 assert res.smoking_allowed == api_pb2.SMOKING_LOCATION_UNKNOWN 

1229 assert not res.HasField("smokes_at_home") 

1230 assert not res.HasField("drinking_allowed") 

1231 assert not res.HasField("drinks_at_home") 

1232 assert not res.HasField("other_host_info") 

1233 assert res.sleeping_arrangement == api_pb2.SLEEPING_ARRANGEMENT_UNKNOWN 

1234 assert not res.HasField("sleeping_details") 

1235 assert not res.HasField("area") 

1236 assert not res.HasField("house_rules") 

1237 assert not res.HasField("parking") 

1238 assert res.parking_details == api_pb2.PARKING_DETAILS_UNKNOWN 

1239 assert not res.HasField("camping_ok") 

1240 

1241 

1242def test_badges(db): 

1243 user1, _ = generate_user() 

1244 user2, _ = generate_user() 

1245 user3, _ = generate_user() 

1246 user4, token = generate_user() 

1247 

1248 update_badges(empty_pb2.Empty()) 

1249 

1250 founder_badge = get_badge_dict()["founder"] 

1251 board_member_badge = get_badge_dict()["board_member"] 

1252 

1253 with api_session(token) as api: 

1254 assert api.GetUser(api_pb2.GetUserReq(user=user1.username)).badges == ["founder", "board_member"] 

1255 assert api.GetUser(api_pb2.GetUserReq(user=user2.username)).badges == ["founder", "board_member"] 

1256 assert api.GetUser(api_pb2.GetUserReq(user=user3.username)).badges == [] 

1257 

1258 assert api.ListBadgeUsers(api_pb2.ListBadgeUsersReq(badge_id=founder_badge["id"])).user_ids == [1, 2] 

1259 res = api.ListBadgeUsers(api_pb2.ListBadgeUsersReq(badge_id=board_member_badge["id"], page_size=1)) 

1260 assert res.user_ids == [1] 

1261 res2 = api.ListBadgeUsers( 

1262 api_pb2.ListBadgeUsersReq(badge_id=board_member_badge["id"], page_token=res.next_page_token) 

1263 ) 

1264 assert res2.user_ids == [2]