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

278 statements  

« prev     ^ index     » next       coverage.py v7.6.10, created at 2025-04-16 15:13 +0000

1from datetime import timedelta 

2 

3import pytest 

4from google.protobuf import wrappers_pb2 

5 

6from couchers.db import session_scope 

7from couchers.models import EventOccurrence, HostingStatus, LanguageAbility, LanguageFluency, MeetupStatus 

8from couchers.utils import Timestamp_from_datetime, create_coordinate, millis_from_dt, now 

9from proto import api_pb2, communities_pb2, events_pb2, search_pb2 

10from tests.test_communities import create_community, testing_communities # noqa 

11from tests.test_fixtures import ( # noqa 

12 communities_session, 

13 db, 

14 events_session, 

15 generate_user, 

16 search_session, 

17 testconfig, 

18) 

19from tests.test_references import create_friend_reference 

20 

21 

22@pytest.fixture(autouse=True) 

23def _(testconfig): 

24 pass 

25 

26 

27def test_Search(testing_communities): 

28 user, token = generate_user() 

29 with search_session(token) as api: 

30 res = api.Search( 

31 search_pb2.SearchReq( 

32 query="Country 1, Region 1", 

33 include_users=True, 

34 include_communities=True, 

35 include_groups=True, 

36 include_places=True, 

37 include_guides=True, 

38 ) 

39 ) 

40 res = api.Search( 

41 search_pb2.SearchReq( 

42 query="Country 1, Region 1, Attraction", 

43 title_only=True, 

44 include_users=True, 

45 include_communities=True, 

46 include_groups=True, 

47 include_places=True, 

48 include_guides=True, 

49 ) 

50 ) 

51 

52 

53def test_UserSearch(testing_communities): 

54 """Test that UserSearch returns all users if no filter is set.""" 

55 user, token = generate_user() 

56 with search_session(token) as api: 

57 res = api.UserSearch(search_pb2.UserSearchReq()) 

58 assert len(res.results) > 0 

59 assert res.total_items == len(res.results) 

60 

61 

62def test_regression_search_in_area(db): 

63 """ 

64 Makes sure search_in_area works. 

65 

66 At the equator/prime meridian intersection (0,0), one degree is roughly 111 km. 

67 """ 

68 

69 # outside 

70 user1, token1 = generate_user(geom=create_coordinate(1, 0), geom_radius=100) 

71 # outside 

72 user2, token2 = generate_user(geom=create_coordinate(0, 1), geom_radius=100) 

73 # inside 

74 user3, token3 = generate_user(geom=create_coordinate(0.1, 0), geom_radius=100) 

75 # inside 

76 user4, token4 = generate_user(geom=create_coordinate(0, 0.1), geom_radius=100) 

77 # outside 

78 user5, token5 = generate_user(geom=create_coordinate(10, 10), geom_radius=100) 

79 

80 with search_session(token5) as api: 

81 res = api.UserSearch( 

82 search_pb2.UserSearchReq( 

83 search_in_area=search_pb2.Area( 

84 lat=0, 

85 lng=0, 

86 radius=100000, 

87 ) 

88 ) 

89 ) 

90 assert [result.user.user_id for result in res.results] == [user3.id, user4.id] 

91 

92 

93def test_user_search_in_rectangle(db): 

94 """ 

95 Makes sure search_in_rectangle works as expected. 

96 """ 

97 

98 # outside 

99 user1, token1 = generate_user(geom=create_coordinate(-1, 0), geom_radius=100) 

100 # outside 

101 user2, token2 = generate_user(geom=create_coordinate(0, -1), geom_radius=100) 

102 # inside 

103 user3, token3 = generate_user(geom=create_coordinate(0.1, 0.1), geom_radius=100) 

104 # inside 

105 user4, token4 = generate_user(geom=create_coordinate(1.2, 0.1), geom_radius=100) 

106 # outside (not fully inside) 

107 user5, token5 = generate_user(geom=create_coordinate(0, 0), geom_radius=100) 

108 # outside 

109 user6, token6 = generate_user(geom=create_coordinate(0.1, 1.2), geom_radius=100) 

110 # outside 

111 user7, token7 = generate_user(geom=create_coordinate(10, 10), geom_radius=100) 

112 

113 with search_session(token5) as api: 

114 res = api.UserSearch( 

115 search_pb2.UserSearchReq( 

116 search_in_rectangle=search_pb2.RectArea( 

117 lat_min=0, 

118 lat_max=2, 

119 lng_min=0, 

120 lng_max=1, 

121 ) 

122 ) 

123 ) 

124 assert [result.user.user_id for result in res.results] == [user3.id, user4.id] 

125 

126 

127def test_user_filter_complete_profile(db): 

128 """ 

129 Make sure the completed profile flag returns only completed user profile 

130 """ 

131 user_complete_profile, token6 = generate_user(complete_profile=True) 

132 

133 user_incomplete_profile, token7 = generate_user(complete_profile=False) 

134 

135 with search_session(token7) as api: 

136 res = api.UserSearch(search_pb2.UserSearchReq(profile_completed=wrappers_pb2.BoolValue(value=False))) 

137 assert user_incomplete_profile.id in [result.user.user_id for result in res.results] 

138 

139 with search_session(token6) as api: 

140 res = api.UserSearch(search_pb2.UserSearchReq(profile_completed=wrappers_pb2.BoolValue(value=True))) 

141 assert [result.user.user_id for result in res.results] == [user_complete_profile.id] 

142 

143 

144def test_user_filter_meetup_status(db): 

145 """ 

146 Make sure the completed profile flag returns only completed user profile 

147 """ 

148 user_wants_to_meetup, token8 = generate_user(meetup_status=MeetupStatus.wants_to_meetup) 

149 

150 user_does_not_want_to_meet, token9 = generate_user(meetup_status=MeetupStatus.does_not_want_to_meetup) 

151 

152 with search_session(token8) as api: 

153 res = api.UserSearch(search_pb2.UserSearchReq(meetup_status_filter=[api_pb2.MEETUP_STATUS_WANTS_TO_MEETUP])) 

154 assert user_wants_to_meetup.id in [result.user.user_id for result in res.results] 

155 

156 with search_session(token9) as api: 

157 res = api.UserSearch( 

158 search_pb2.UserSearchReq(meetup_status_filter=[api_pb2.MEETUP_STATUS_DOES_NOT_WANT_TO_MEETUP]) 

159 ) 

160 assert [result.user.user_id for result in res.results] == [user_does_not_want_to_meet.id] 

161 

162 

163def test_user_filter_language(db): 

164 """ 

165 Test filtering users by language ability. 

166 """ 

167 user_with_german_beginner, token11 = generate_user(hosting_status=HostingStatus.can_host) 

168 user_with_japanese_conversational, token12 = generate_user(hosting_status=HostingStatus.can_host) 

169 user_with_german_fluent, token13 = generate_user(hosting_status=HostingStatus.can_host) 

170 

171 with session_scope() as session: 

172 session.add( 

173 LanguageAbility( 

174 user_id=user_with_german_beginner.id, language_code="deu", fluency=LanguageFluency.beginner 

175 ), 

176 ) 

177 session.add( 

178 LanguageAbility( 

179 user_id=user_with_japanese_conversational.id, 

180 language_code="jpn", 

181 fluency=LanguageFluency.fluent, 

182 ) 

183 ) 

184 session.add( 

185 LanguageAbility(user_id=user_with_german_fluent.id, language_code="deu", fluency=LanguageFluency.fluent) 

186 ) 

187 

188 with search_session(token11) as api: 

189 res = api.UserSearch( 

190 search_pb2.UserSearchReq( 

191 language_ability_filter=[ 

192 api_pb2.LanguageAbility( 

193 code="deu", 

194 fluency=api_pb2.LanguageAbility.Fluency.FLUENCY_FLUENT, 

195 ) 

196 ] 

197 ) 

198 ) 

199 assert [result.user.user_id for result in res.results] == [user_with_german_fluent.id] 

200 

201 res = api.UserSearch( 

202 search_pb2.UserSearchReq( 

203 language_ability_filter=[ 

204 api_pb2.LanguageAbility( 

205 code="jpn", 

206 fluency=api_pb2.LanguageAbility.Fluency.FLUENCY_CONVERSATIONAL, 

207 ) 

208 ] 

209 ) 

210 ) 

211 assert [result.user.user_id for result in res.results] == [user_with_japanese_conversational.id] 

212 

213 

214def test_user_filter_strong_verification(db): 

215 user1, token1 = generate_user() 

216 user2, _ = generate_user(strong_verification=True) 

217 user3, _ = generate_user() 

218 user4, _ = generate_user(strong_verification=True) 

219 user5, _ = generate_user(strong_verification=True) 

220 

221 with search_session(token1) as api: 

222 res = api.UserSearch(search_pb2.UserSearchReq(only_with_strong_verification=False)) 

223 assert [result.user.user_id for result in res.results] == [user1.id, user2.id, user3.id, user4.id, user5.id] 

224 

225 res = api.UserSearch(search_pb2.UserSearchReq(only_with_strong_verification=True)) 

226 assert [result.user.user_id for result in res.results] == [user2.id, user4.id, user5.id] 

227 

228 

229def test_regression_search_only_with_references(db): 

230 user1, token1 = generate_user() 

231 user2, _ = generate_user() 

232 user3, _ = generate_user() 

233 user4, _ = generate_user(delete_user=True) 

234 

235 with session_scope() as session: 

236 # user 2 has references 

237 create_friend_reference(session, user1.id, user2.id, timedelta(days=1)) 

238 create_friend_reference(session, user3.id, user2.id, timedelta(days=1)) 

239 create_friend_reference(session, user4.id, user2.id, timedelta(days=1)) 

240 

241 # user 3 only has reference from a deleted user 

242 create_friend_reference(session, user4.id, user3.id, timedelta(days=1)) 

243 

244 with search_session(token1) as api: 

245 res = api.UserSearch(search_pb2.UserSearchReq(only_with_references=False)) 

246 assert [result.user.user_id for result in res.results] == [user1.id, user2.id, user3.id] 

247 

248 res = api.UserSearch(search_pb2.UserSearchReq(only_with_references=True)) 

249 assert [result.user.user_id for result in res.results] == [user2.id] 

250 

251 

252def test_user_search_exactly_user_ids(db): 

253 """ 

254 Test that UserSearch with exactly_user_ids returns only those users and ignores other filters. 

255 """ 

256 # Create users with different properties 

257 user1, token1 = generate_user() 

258 user2, _ = generate_user(strong_verification=True) 

259 user3, _ = generate_user(complete_profile=True) 

260 user4, _ = generate_user(meetup_status=MeetupStatus.wants_to_meetup) 

261 user5, _ = generate_user(delete_user=True) # Deleted user 

262 

263 with search_session(token1) as api: 

264 # Test that exactly_user_ids returns only the specified users 

265 res = api.UserSearch(search_pb2.UserSearchReq(exactly_user_ids=[user2.id, user3.id, user4.id])) 

266 assert sorted([result.user.user_id for result in res.results]) == sorted([user2.id, user3.id, user4.id]) 

267 

268 # Test that exactly_user_ids ignores other filters 

269 res = api.UserSearch( 

270 search_pb2.UserSearchReq( 

271 exactly_user_ids=[user2.id, user3.id, user4.id], 

272 only_with_strong_verification=True, # This would normally filter out user3 and user4 

273 ) 

274 ) 

275 assert sorted([result.user.user_id for result in res.results]) == sorted([user2.id, user3.id, user4.id]) 

276 

277 # Test with non-existent user IDs (should be ignored) 

278 res = api.UserSearch(search_pb2.UserSearchReq(exactly_user_ids=[user1.id, 99999])) 

279 assert [result.user.user_id for result in res.results] == [user1.id] 

280 

281 # Test with deleted user ID (should be ignored due to visibility filter) 

282 res = api.UserSearch(search_pb2.UserSearchReq(exactly_user_ids=[user1.id, user5.id])) 

283 assert [result.user.user_id for result in res.results] == [user1.id] 

284 

285 

286@pytest.fixture 

287def sample_event_data() -> dict: 

288 """Dummy data for creating events.""" 

289 start_time = now() + timedelta(hours=2) 

290 end_time = start_time + timedelta(hours=3) 

291 return { 

292 "title": "Dummy Title", 

293 "content": "Dummy content.", 

294 "photo_key": None, 

295 "offline_information": events_pb2.OfflineEventInformation(address="Near Null Island", lat=0.1, lng=0.2), 

296 "start_time": Timestamp_from_datetime(start_time), 

297 "end_time": Timestamp_from_datetime(end_time), 

298 "timezone": "UTC", 

299 } 

300 

301 

302@pytest.fixture 

303def create_event(sample_event_data): 

304 """Factory for creating events.""" 

305 

306 def _create_event(event_api, **kwargs) -> EventOccurrence: 

307 """Create an event with default values, unless overridden by kwargs.""" 

308 return event_api.CreateEvent(events_pb2.CreateEventReq(**{**sample_event_data, **kwargs})) 

309 

310 return _create_event 

311 

312 

313@pytest.fixture 

314def sample_community(db) -> int: 

315 """Create large community spanning from (-50, 0) to (50, 2) as events can only be created within communities.""" 

316 user, _ = generate_user() 

317 with session_scope() as session: 

318 return create_community(session, -50, 50, "Community", [user], [], None).id 

319 

320 

321def test_EventSearch_no_filters(testing_communities): 

322 """Test that EventSearch returns all events if no filter is set.""" 

323 user, token = generate_user() 

324 with search_session(token) as api: 

325 res = api.EventSearch(search_pb2.EventSearchReq()) 

326 assert len(res.events) > 0 

327 

328 

329def test_event_search_by_query(sample_community, create_event): 

330 """Test that EventSearch finds events by title (and content if query_title_only=False).""" 

331 user, token = generate_user() 

332 

333 with events_session(token) as api: 

334 event1 = create_event(api, title="Lorem Ipsum") 

335 event2 = create_event(api, content="Lorem Ipsum") 

336 create_event(api) 

337 

338 with search_session(token) as api: 

339 res = api.EventSearch(search_pb2.EventSearchReq(query=wrappers_pb2.StringValue(value="Ipsum"))) 

340 assert len(res.events) == 2 

341 assert {result.event_id for result in res.events} == {event1.event_id, event2.event_id} 

342 

343 res = api.EventSearch( 

344 search_pb2.EventSearchReq(query=wrappers_pb2.StringValue(value="Ipsum"), query_title_only=True) 

345 ) 

346 assert len(res.events) == 1 

347 assert res.events[0].event_id == event1.event_id 

348 

349 

350def test_event_search_by_time(sample_community, create_event): 

351 """Test that EventSearch filters with the given time range.""" 

352 user, token = generate_user() 

353 

354 with events_session(token) as api: 

355 event1 = create_event( 

356 api, 

357 start_time=Timestamp_from_datetime(now() + timedelta(hours=1)), 

358 end_time=Timestamp_from_datetime(now() + timedelta(hours=2)), 

359 ) 

360 event2 = create_event( 

361 api, 

362 start_time=Timestamp_from_datetime(now() + timedelta(hours=4)), 

363 end_time=Timestamp_from_datetime(now() + timedelta(hours=5)), 

364 ) 

365 event3 = create_event( 

366 api, 

367 start_time=Timestamp_from_datetime(now() + timedelta(hours=7)), 

368 end_time=Timestamp_from_datetime(now() + timedelta(hours=8)), 

369 ) 

370 

371 with search_session(token) as api: 

372 res = api.EventSearch(search_pb2.EventSearchReq(before=Timestamp_from_datetime(now() + timedelta(hours=6)))) 

373 assert len(res.events) == 2 

374 assert {result.event_id for result in res.events} == {event1.event_id, event2.event_id} 

375 

376 res = api.EventSearch(search_pb2.EventSearchReq(after=Timestamp_from_datetime(now() + timedelta(hours=3)))) 

377 assert len(res.events) == 2 

378 assert {result.event_id for result in res.events} == {event2.event_id, event3.event_id} 

379 

380 res = api.EventSearch( 

381 search_pb2.EventSearchReq( 

382 before=Timestamp_from_datetime(now() + timedelta(hours=6)), 

383 after=Timestamp_from_datetime(now() + timedelta(hours=3)), 

384 ) 

385 ) 

386 assert len(res.events) == 1 

387 assert res.events[0].event_id == event2.event_id 

388 

389 

390def test_event_search_by_circle(sample_community, create_event): 

391 """Test that EventSearch only returns events within the given circle.""" 

392 user, token = generate_user() 

393 

394 with events_session(token) as api: 

395 inside_pts = [(0.1, 0.01), (0.01, 0.1)] 

396 for i, (lat, lng) in enumerate(inside_pts): 

397 create_event( 

398 api, 

399 title=f"Inside area {i}", 

400 offline_information=events_pb2.OfflineEventInformation(lat=lat, lng=lng, address=f"Inside area {i}"), 

401 ) 

402 

403 outside_pts = [(1, 0.1), (0.1, 1), (10, 1)] 

404 for i, (lat, lng) in enumerate(outside_pts): 

405 create_event( 

406 api, 

407 title=f"Outside area {i}", 

408 offline_information=events_pb2.OfflineEventInformation(lat=lat, lng=lng, address=f"Outside area {i}"), 

409 ) 

410 

411 with search_session(token) as api: 

412 res = api.EventSearch(search_pb2.EventSearchReq(search_in_area=search_pb2.Area(lat=0, lng=0, radius=100000))) 

413 assert len(res.events) == len(inside_pts) 

414 assert all(event.title.startswith("Inside area") for event in res.events) 

415 

416 

417def test_event_search_by_rectangle(sample_community, create_event): 

418 """Test that EventSearch only returns events within the given rectangular area.""" 

419 user, token = generate_user() 

420 

421 with events_session(token) as api: 

422 inside_pts = [(0.1, 0.2), (1.2, 0.2)] 

423 for i, (lat, lng) in enumerate(inside_pts): 

424 create_event( 

425 api, 

426 title=f"Inside area {i}", 

427 offline_information=events_pb2.OfflineEventInformation(lat=lat, lng=lng, address=f"Inside area {i}"), 

428 ) 

429 

430 outside_pts = [(-1, 0.1), (0.1, 0.01), (-0.01, 0.01), (0.1, 1.2), (10, 1)] 

431 for i, (lat, lng) in enumerate(outside_pts): 

432 create_event( 

433 api, 

434 title=f"Outside area {i}", 

435 offline_information=events_pb2.OfflineEventInformation(lat=lat, lng=lng, address=f"Outside area {i}"), 

436 ) 

437 

438 with search_session(token) as api: 

439 res = api.EventSearch( 

440 search_pb2.EventSearchReq( 

441 search_in_rectangle=search_pb2.RectArea(lat_min=0, lat_max=2, lng_min=0.1, lng_max=1) 

442 ) 

443 ) 

444 assert len(res.events) == len(inside_pts) 

445 assert all(event.title.startswith("Inside area") for event in res.events) 

446 

447 

448def test_event_search_pagination(sample_community, create_event): 

449 """Test that EventSearch paginates correctly. 

450 

451 Check that 

452 - <page_size> events are returned, if available 

453 - sort order is applied (default: past=False) 

454 - the next page token is correct 

455 """ 

456 user, token = generate_user() 

457 

458 anchor_time = now() 

459 with events_session(token) as api: 

460 for i in range(5): 

461 create_event( 

462 api, 

463 title=f"Event {i + 1}", 

464 start_time=Timestamp_from_datetime(anchor_time + timedelta(hours=i + 1)), 

465 end_time=Timestamp_from_datetime(anchor_time + timedelta(hours=i + 1, minutes=30)), 

466 ) 

467 

468 with search_session(token) as api: 

469 res = api.EventSearch(search_pb2.EventSearchReq(past=False, page_size=4)) 

470 assert len(res.events) == 4 

471 assert [event.title for event in res.events] == ["Event 1", "Event 2", "Event 3", "Event 4"] 

472 assert res.next_page_token == str(millis_from_dt(anchor_time + timedelta(hours=5, minutes=30))) 

473 

474 res = api.EventSearch(search_pb2.EventSearchReq(page_size=4, page_token=res.next_page_token)) 

475 assert len(res.events) == 1 

476 assert res.events[0].title == "Event 5" 

477 assert res.next_page_token == "" 

478 

479 res = api.EventSearch( 

480 search_pb2.EventSearchReq( 

481 past=True, page_size=2, page_token=str(millis_from_dt(anchor_time + timedelta(hours=4, minutes=30))) 

482 ) 

483 ) 

484 assert len(res.events) == 2 

485 assert [event.title for event in res.events] == ["Event 4", "Event 3"] 

486 assert res.next_page_token == str(millis_from_dt(anchor_time + timedelta(hours=2, minutes=30))) 

487 

488 res = api.EventSearch(search_pb2.EventSearchReq(past=True, page_size=2, page_token=res.next_page_token)) 

489 assert len(res.events) == 2 

490 assert [event.title for event in res.events] == ["Event 2", "Event 1"] 

491 assert res.next_page_token == "" 

492 

493 

494def test_event_search_pagination_with_page_number(sample_community, create_event): 

495 """Test that EventSearch paginates correctly with page number. 

496 

497 Check that 

498 - <page_size> events are returned, if available 

499 - sort order is applied (default: past=False) 

500 - <page_number> is respected 

501 - <total_items> is correct 

502 """ 

503 user, token = generate_user() 

504 

505 anchor_time = now() 

506 with events_session(token) as api: 

507 for i in range(5): 

508 create_event( 

509 api, 

510 title=f"Event {i + 1}", 

511 start_time=Timestamp_from_datetime(anchor_time + timedelta(hours=i + 1)), 

512 end_time=Timestamp_from_datetime(anchor_time + timedelta(hours=i + 1, minutes=30)), 

513 ) 

514 

515 with search_session(token) as api: 

516 res = api.EventSearch(search_pb2.EventSearchReq(page_size=2, page_number=1)) 

517 assert len(res.events) == 2 

518 assert [event.title for event in res.events] == ["Event 1", "Event 2"] 

519 assert res.total_items == 5 

520 

521 res = api.EventSearch(search_pb2.EventSearchReq(page_size=2, page_number=2)) 

522 assert len(res.events) == 2 

523 assert [event.title for event in res.events] == ["Event 3", "Event 4"] 

524 assert res.total_items == 5 

525 

526 res = api.EventSearch(search_pb2.EventSearchReq(page_size=2, page_number=3)) 

527 assert len(res.events) == 1 

528 assert [event.title for event in res.events] == ["Event 5"] 

529 assert res.total_items == 5 

530 

531 # Verify no more pages 

532 res = api.EventSearch(search_pb2.EventSearchReq(page_size=2, page_number=4)) 

533 assert not res.events 

534 assert res.total_items == 5 

535 

536 

537def test_event_search_online_status(sample_community, create_event): 

538 """Test that EventSearch respects only_online and only_offline filters and by default returns both.""" 

539 user, token = generate_user() 

540 

541 with events_session(token) as api: 

542 create_event(api, title="Offline event") 

543 

544 create_event( 

545 api, 

546 title="Online event", 

547 online_information=events_pb2.OnlineEventInformation(link="https://couchers.org/meet/"), 

548 parent_community_id=sample_community, 

549 offline_information=events_pb2.OfflineEventInformation(), 

550 ) 

551 

552 with search_session(token) as api: 

553 res = api.EventSearch(search_pb2.EventSearchReq()) 

554 assert len(res.events) == 2 

555 assert {event.title for event in res.events} == {"Offline event", "Online event"} 

556 

557 res = api.EventSearch(search_pb2.EventSearchReq(only_online=True)) 

558 assert {event.title for event in res.events} == {"Online event"} 

559 

560 res = api.EventSearch(search_pb2.EventSearchReq(only_offline=True)) 

561 assert {event.title for event in res.events} == {"Offline event"} 

562 

563 

564def test_event_search_filter_subscription_attendance_organizing_my_communities(sample_community, create_event): 

565 """Test that EventSearch respects subscribed, attending, organizing and my_communities filters and by default 

566 returns all events. 

567 """ 

568 _, token = generate_user() 

569 other_user, other_token = generate_user() 

570 

571 with communities_session(token) as api: 

572 api.JoinCommunity(communities_pb2.JoinCommunityReq(community_id=sample_community)) 

573 

574 with session_scope() as session: 

575 create_community(session, 55, 60, "Other community", [other_user], [], None) 

576 

577 with events_session(other_token) as api: 

578 e_subscribed = create_event(api, title="Subscribed event") 

579 e_attending = create_event(api, title="Attending event") 

580 create_event(api, title="Community event") 

581 create_event( 

582 api, 

583 title="Other community event", 

584 offline_information=events_pb2.OfflineEventInformation(lat=58, lng=1, address="Somewhere"), 

585 ) 

586 

587 with events_session(token) as api: 

588 create_event(api, title="Organized event") 

589 api.SetEventSubscription(events_pb2.SetEventSubscriptionReq(event_id=e_subscribed.event_id, subscribe=True)) 

590 api.SetEventAttendance( 

591 events_pb2.SetEventAttendanceReq( 

592 event_id=e_attending.event_id, attendance_state=events_pb2.ATTENDANCE_STATE_GOING 

593 ) 

594 ) 

595 

596 with search_session(token) as api: 

597 res = api.EventSearch(search_pb2.EventSearchReq()) 

598 assert {event.title for event in res.events} == { 

599 "Subscribed event", 

600 "Attending event", 

601 "Community event", 

602 "Other community event", 

603 "Organized event", 

604 } 

605 

606 res = api.EventSearch(search_pb2.EventSearchReq(subscribed=True)) 

607 assert {event.title for event in res.events} == {"Subscribed event", "Organized event"} 

608 

609 res = api.EventSearch(search_pb2.EventSearchReq(attending=True)) 

610 assert {event.title for event in res.events} == {"Attending event", "Organized event"} 

611 

612 res = api.EventSearch(search_pb2.EventSearchReq(organizing=True)) 

613 assert {event.title for event in res.events} == {"Organized event"} 

614 

615 res = api.EventSearch(search_pb2.EventSearchReq(my_communities=True)) 

616 assert {event.title for event in res.events} == { 

617 "Subscribed event", 

618 "Attending event", 

619 "Community event", 

620 "Organized event", 

621 } 

622 

623 res = api.EventSearch(search_pb2.EventSearchReq(subscribed=True, attending=True)) 

624 assert {event.title for event in res.events} == {"Subscribed event", "Attending event", "Organized event"}