From ad847a82c871bc63f65350dff75bc977f21d877d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Tue, 21 Jan 2025 11:58:28 +0100 Subject: [PATCH] refactor: Remove `TestHelper` in `pinned_events.rs` Use helper functions instead. --- .../integration/timeline/pinned_event.rs | 544 +++++++++--------- 1 file changed, 258 insertions(+), 286 deletions(-) diff --git a/crates/matrix-sdk-ui/tests/integration/timeline/pinned_event.rs b/crates/matrix-sdk-ui/tests/integration/timeline/pinned_event.rs index 3089c0c08..dfbf12b26 100644 --- a/crates/matrix-sdk-ui/tests/integration/timeline/pinned_event.rs +++ b/crates/matrix-sdk-ui/tests/integration/timeline/pinned_event.rs @@ -10,7 +10,7 @@ use matrix_sdk::{ logged_in_client_with_server, mocks::{MatrixMockServer, RoomMessagesResponseTemplate}, }, - Client, + Client, Room, }; use matrix_sdk_base::deserialized_responses::TimelineEvent; use matrix_sdk_test::{ @@ -29,12 +29,13 @@ use ruma::{ EncryptedEventScheme, MegolmV1AesSha2ContentInit, RoomEncryptedEventContent, }, message::RoomMessageEventContentWithoutRelation, + pinned_events::RoomPinnedEventsEventContent, }, - AnyTimelineEvent, + AnySyncTimelineEvent, }, - owned_device_id, owned_room_id, owned_user_id, + owned_device_id, owned_room_id, owned_user_id, room_id, serde::Raw, - EventId, MilliSecondsSinceUnixEpoch, OwnedRoomId, RoomId, UserId, + user_id, EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedRoomId, RoomId, UserId, }; use serde_json::json; use stream_assert::assert_pending; @@ -48,27 +49,27 @@ use crate::mock_sync; #[async_test] async fn test_new_pinned_events_are_added_on_sync() { - let mut test_helper = TestHelper::new().await; - let room_id = test_helper.room_id.clone(); + let server = MatrixMockServer::new().await; + let client = server.client_builder().build().await; + let room_id = room_id!("!test:localhost"); - // Join the room - let _ = test_helper.do_initial_sync().await; - - let f = EventFactory::new().room(&room_id).sender(*BOB); + let f = EventFactory::new().room(room_id).sender(*BOB); let event_1 = f .text_msg("in the end") .event_id(event_id!("$1")) .server_ts(MilliSecondsSinceUnixEpoch::now()) - .into_timeline(); + .into_raw_sync(); // Mock /event endpoint for a timeline event - test_helper.mock_events(vec![event_1.clone()]).await; + mock_events_endpoint(&server, room_id, vec![event_1]).await; // Load initial timeline items: a `m.room.pinned_events` with events $1 and $2 // pinned - test_helper.sync_once(Vec::new(), Some(vec!["$1", "$2"])).await.expect("Sync failed"); - - let room = test_helper.client.get_room(&room_id).unwrap(); + let room = PinnedEventsSync::new(room_id) + .with_pinned_event_ids(vec!["$1", "$2"]) + .mock_and_sync(&client, &server) + .await + .expect("Room should be synced"); let timeline = Timeline::builder(&room).with_focus(pinned_events_focus(100)).build().await.unwrap(); @@ -91,14 +92,19 @@ async fn test_new_pinned_events_are_added_on_sync() { .text_msg("pinned message!") .event_id(event_id!("$2")) .server_ts(MilliSecondsSinceUnixEpoch::now()) - .into_timeline(); + .into_raw_sync(); let event_3 = f .text_msg("normal message") .event_id(event_id!("$3")) .server_ts(MilliSecondsSinceUnixEpoch::now()) - .into_timeline(); - test_helper.mock_events(vec![event_2.clone(), event_3.clone()]).await; - test_helper.sync_once(vec![event_2, event_3], None).await.expect("Sync failed"); + .into_raw_sync(); + mock_events_endpoint(&server, room_id, vec![event_2.clone(), event_3.clone()]).await; + + let _ = PinnedEventsSync::new(room_id) + .with_timeline_events(vec![event_2, event_3]) + .mock_and_sync(&client, &server) + .await + .expect("Room should be synced"); // The item is added automatically assert_next_matches_with_timeout!(timeline_stream, VectorDiff::PushBack { value } => { @@ -120,30 +126,32 @@ async fn test_new_pinned_events_are_added_on_sync() { #[async_test] async fn test_new_pinned_event_ids_reload_the_timeline() { - let mut test_helper = TestHelper::new().await; - let room_id = test_helper.room_id.clone(); + let server = MatrixMockServer::new().await; + let client = server.client_builder().build().await; + let room_id = room_id!("!test:localhost"); - // Join the room - test_helper.do_initial_sync().await; - - let f = EventFactory::new().room(&room_id).sender(*BOB); + let f = EventFactory::new().room(room_id).sender(*BOB); let event_1 = f .text_msg("in the end") .event_id(event_id!("$1")) .server_ts(MilliSecondsSinceUnixEpoch::now()) - .into_timeline(); + .into_raw_sync(); let event_2 = f .text_msg("it doesn't even matter") .event_id(event_id!("$2")) .server_ts(MilliSecondsSinceUnixEpoch::now()) - .into_timeline(); + .into_raw_sync(); // Load initial timeline items: 2 text messages and a `m.room.pinned_events` // with event $1 and $2 pinned - test_helper.mock_events(vec![event_1.clone(), event_2.clone()]).await; - let _ = test_helper.sync_once(vec![event_2.clone()], Some(vec!["$1"])).await; + mock_events_endpoint(&server, room_id, vec![event_1.clone(), event_2.clone()]).await; + let room = PinnedEventsSync::new(room_id) + .with_timeline_events(vec![event_2.clone()]) + .with_pinned_event_ids(vec!["$1"]) + .mock_and_sync(&client, &server) + .await + .expect("Room should be synced"); - let room = test_helper.client.get_room(&room_id).unwrap(); let timeline = Timeline::builder(&room).with_focus(pinned_events_focus(100)).build().await.unwrap(); @@ -160,8 +168,12 @@ async fn test_new_pinned_event_ids_reload_the_timeline() { assert_pending!(timeline_stream); // Reload timeline with new pinned event ids - test_helper.mock_events(vec![event_1.clone(), event_2.clone()]).await; - test_helper.sync_once(Vec::new(), Some(vec!["$1", "$2"])).await.expect("Sync failed"); + mock_events_endpoint(&server, room_id, vec![event_1.clone(), event_2.clone()]).await; + let _ = PinnedEventsSync::new(room_id) + .with_pinned_event_ids(vec!["$1", "$2"]) + .mock_and_sync(&client, &server) + .await + .expect("Sync failed"); assert_next_matches_with_timeout!(timeline_stream, VectorDiff::Clear); assert_next_matches_with_timeout!(timeline_stream, VectorDiff::PushBack { value } => { @@ -176,8 +188,12 @@ async fn test_new_pinned_event_ids_reload_the_timeline() { assert_pending!(timeline_stream); // Reload timeline with no pinned event - test_helper.mock_events(vec![event_1.clone(), event_2.clone()]).await; - let _ = test_helper.sync_once(Vec::new(), Some(Vec::new())).await; + mock_events_endpoint(&server, room_id, vec![event_1.clone(), event_2.clone()]).await; + let _ = PinnedEventsSync::new(room_id) + .with_pinned_event_ids(Vec::new()) + .mock_and_sync(&client, &server) + .await + .expect("Sync failed"); assert_next_matches_with_timeout!(timeline_stream, VectorDiff::Clear); assert_pending!(timeline_stream); @@ -185,25 +201,26 @@ async fn test_new_pinned_event_ids_reload_the_timeline() { #[async_test] async fn test_max_events_to_load_is_honored() { - let mut test_helper = TestHelper::new().await; - let room_id = test_helper.room_id.clone(); + let server = MatrixMockServer::new().await; + let client = server.client_builder().build().await; + let room_id = room_id!("!test:localhost"); - // Join the room - let _ = test_helper.do_initial_sync().await; - - let f = EventFactory::new().room(&room_id).sender(*BOB); + let f = EventFactory::new().room(room_id).sender(*BOB); let pinned_event = f .text_msg("in the end") .event_id(event_id!("$1")) .server_ts(MilliSecondsSinceUnixEpoch::now()) - .into_timeline(); + .into_raw_sync(); // Load initial timeline items: a text message and a `m.room.pinned_events` // with event $1 and $2 pinned - test_helper.mock_events(vec![pinned_event]).await; - test_helper.sync_once(Vec::new(), Some(vec!["$1", "$2"])).await.expect("Sync failed"); + mock_events_endpoint(&server, room_id, vec![pinned_event]).await; + let room = PinnedEventsSync::new(room_id) + .with_pinned_event_ids(vec!["$1", "$2"]) + .mock_and_sync(&client, &server) + .await + .expect("Sync failed"); - let room = test_helper.client.get_room(&room_id).unwrap(); let ret = Timeline::builder(&room).with_focus(pinned_events_focus(1)).build().await; // We're only taking the last event id, `$2`, and it's not available so the @@ -213,31 +230,31 @@ async fn test_max_events_to_load_is_honored() { #[async_test] async fn test_cached_events_are_kept_for_different_room_instances() { - let mut test_helper = TestHelper::new().await; + let server = MatrixMockServer::new().await; + let client = server.client_builder().build().await; + let room_id = room_id!("!test:localhost"); // Subscribe to the event cache. - test_helper.client.event_cache().subscribe().unwrap(); + client.event_cache().subscribe().unwrap(); - let room_id = test_helper.room_id.clone(); - - // Join the room - test_helper.do_initial_sync().await; - - let f = EventFactory::new().room(&room_id).sender(*BOB); + let f = EventFactory::new().room(room_id).sender(*BOB); let pinned_event = f .text_msg("in the end") .event_id(event_id!("$1")) .server_ts(MilliSecondsSinceUnixEpoch::now()) - .into_timeline(); + .into_raw_sync(); // Mock /event for some timeline events - test_helper.mock_events(vec![pinned_event]).await; + mock_events_endpoint(&server, room_id, vec![pinned_event]).await; // Load initial timeline items: a `m.room.pinned_events` with event $1 and $2 // pinned - test_helper.sync_once(Vec::new(), Some(vec!["$1", "$2"])).await.expect("Sync failed"); + let room = PinnedEventsSync::new(room_id) + .with_pinned_event_ids(vec!["$1", "$2"]) + .mock_and_sync(&client, &server) + .await + .expect("Sync failed"); - let room = test_helper.client.get_room(&room_id).unwrap(); let (room_cache, _drop_handles) = room.event_cache().await.unwrap(); let timeline = Timeline::builder(&room).with_focus(pinned_events_focus(2)).build().await.unwrap(); @@ -261,10 +278,11 @@ async fn test_cached_events_are_kept_for_different_room_instances() { // Set up a sync response with only the pinned event ids and no events, so if // they exist later we know they come from the cache - test_helper.sync_once(Vec::new(), Some(vec!["$1", "$2"])).await.expect("Sync failed"); - - // Get a new room instance - let room = test_helper.client.get_room(&room_id).unwrap(); + let room = PinnedEventsSync::new(room_id) + .with_pinned_event_ids(vec!["$1", "$2"]) + .mock_and_sync(&client, &server) + .await + .expect("Sync failed"); // And a new timeline one let timeline = @@ -275,17 +293,17 @@ async fn test_cached_events_are_kept_for_different_room_instances() { assert!(room_cache.event(event_id!("$1")).await.is_some()); // Drop the existing room and timeline instances - test_helper.server.server().reset().await; + server.server().reset().await; drop(timeline); drop(room); // Now remove the pinned events from the cache and try again - test_helper.client.event_cache().empty_immutable_cache().await; - - test_helper.sync_once(Vec::new(), Some(vec!["$1", "$2"])).await.expect("Sync failed"); - - // Get a new room instance - let room = test_helper.client.get_room(&room_id).unwrap(); + client.event_cache().empty_immutable_cache().await; + let room = PinnedEventsSync::new(room_id) + .with_pinned_event_ids(vec!["$1", "$2"]) + .mock_and_sync(&client, &server) + .await + .expect("Sync failed"); // And a new timeline one let ret = Timeline::builder(&room).with_focus(pinned_events_focus(2)).build().await; @@ -297,17 +315,17 @@ async fn test_cached_events_are_kept_for_different_room_instances() { #[async_test] async fn test_pinned_timeline_with_pinned_event_ids_and_empty_result_fails() { - let mut test_helper = TestHelper::new().await; - let room_id = test_helper.room_id.clone(); - - // Join the room - test_helper.do_initial_sync().await; + let server = MatrixMockServer::new().await; + let client = server.client_builder().build().await; + let room_id = room_id!("!test:localhost"); // Load initial timeline items: a `m.room.pinned_events` with event $1 and $2 // pinned, but they're not available neither in the cache nor in the HS - test_helper.sync_once(Vec::new(), Some(vec!["$1", "$2"])).await.expect("Sync failed"); - - let room = test_helper.client.get_room(&room_id).unwrap(); + let room = PinnedEventsSync::new(room_id) + .with_pinned_event_ids(vec!["$1", "$2"]) + .mock_and_sync(&client, &server) + .await + .expect("Sync failed"); let ret = Timeline::builder(&room).with_focus(pinned_events_focus(1)).build().await; // The timeline couldn't load any events so it fails to initialise @@ -316,16 +334,16 @@ async fn test_pinned_timeline_with_pinned_event_ids_and_empty_result_fails() { #[async_test] async fn test_pinned_timeline_with_no_pinned_event_ids_is_just_empty() { - let mut test_helper = TestHelper::new().await; - let room_id = test_helper.room_id.clone(); - - // Join the room - test_helper.do_initial_sync().await; + let server = MatrixMockServer::new().await; + let client = server.client_builder().build().await; + let room_id = room_id!("!test:localhost"); // Load initial timeline items: an empty `m.room.pinned_events` event - test_helper.sync_once(Vec::new(), Some(Vec::new())).await.expect("Sync failed"); - - let room = test_helper.client.get_room(&room_id).unwrap(); + let room = PinnedEventsSync::new(room_id) + .with_pinned_event_ids(Vec::new()) + .mock_and_sync(&client, &server) + .await + .expect("Sync failed"); let timeline = Timeline::builder(&room).with_focus(pinned_events_focus(1)).build().await.unwrap(); @@ -337,39 +355,23 @@ async fn test_pinned_timeline_with_no_pinned_event_ids_is_just_empty() { #[async_test] async fn test_pinned_timeline_with_no_pinned_events_and_an_utd_on_sync_is_just_empty() { - let mut test_helper = TestHelper::new().await; - let room_id = test_helper.room_id.clone(); + let server = MatrixMockServer::new().await; + let client = server.client_builder().build().await; + let room_id = room_id!("!test:localhost"); let event_id = event_id!("$1:morpheus.localhost"); let sender_id = owned_user_id!("@example:localhost"); - // Join the room - let joined_room_builder = JoinedRoomBuilder::new(&room_id) - // Set up encryption - .add_state_event(StateTestEvent::Encryption); - - // Sync the joined room - test_helper - .server - .mock_sync() - .ok_and_run(&test_helper.client, move |sync_builder| { - sync_builder.add_joined_room(joined_room_builder); - }) - .await; - // Load initial timeline items: an empty `m.room.pinned_events` event - test_helper.sync_once(Vec::new(), Some(Vec::new())).await.expect("Sync failed"); + let room = PinnedEventsSync::new(room_id) + .with_pinned_event_ids(Vec::new()) + .mock_and_sync(&client, &server) + .await + .expect("Sync failed"); // Mock encrypted event for which we don't have keys (an UTD) - let utd_event = create_utd(&room_id, &sender_id, event_id); - test_helper - .server - .mock_room_event() - .match_event_id() - .ok(TimelineEvent::new(utd_event)) - .mount() - .await; + let utd_event = create_utd(room_id, &sender_id, event_id); + mock_events_endpoint(&server, room_id, vec![utd_event]).await; - let room = test_helper.client.get_room(&room_id).unwrap(); let timeline = Timeline::builder(&room).with_focus(pinned_events_focus(1)).build().await.unwrap(); @@ -381,29 +383,18 @@ async fn test_pinned_timeline_with_no_pinned_events_and_an_utd_on_sync_is_just_e #[async_test] async fn test_pinned_timeline_with_no_pinned_events_on_pagination_is_just_empty() { - let mut test_helper = TestHelper::new().await; - let room_id = test_helper.room_id.clone(); + let server = MatrixMockServer::new().await; + let client = server.client_builder().build().await; + let room_id = room_id!("!test:localhost"); let event_id = event_id!("$1.localhost"); let sender_id = owned_user_id!("@example:localhost"); - // Join the room - let joined_room_builder = JoinedRoomBuilder::new(&room_id) - // Set up encryption - .add_state_event(StateTestEvent::Encryption); - - // Sync the joined room - test_helper - .server - .mock_sync() - .ok_and_run(&test_helper.client, move |sync_builder| { - sync_builder.add_joined_room(joined_room_builder); - }) - .await; - // Load initial timeline items: an empty `m.room.pinned_events` event - test_helper.sync_once(Vec::new(), Some(Vec::new())).await.expect("Sync failed"); - - let room = test_helper.client.get_room(&room_id).unwrap(); + let room = PinnedEventsSync::new(room_id) + .with_pinned_event_ids(Vec::new()) + .mock_and_sync(&client, &server) + .await + .expect("Sync failed"); let pinned_timeline = Timeline::builder(&room).with_focus(pinned_events_focus(1)).build().await.unwrap(); @@ -414,14 +405,13 @@ async fn test_pinned_timeline_with_no_pinned_events_on_pagination_is_just_empty( // Create a non-pinned event to return in the pagination let not_pinned_event = EventFactory::new() - .room(&room_id) + .room(room_id) .sender(&sender_id) .text_msg("Hey") .event_id(event_id) .into_raw_timeline(); - test_helper - .server + server .mock_room_messages() .ok(assign!(RoomMessagesResponseTemplate::default(), { chunk: vec![not_pinned_event] @@ -456,53 +446,23 @@ async fn test_pinned_timeline_with_no_pinned_events_on_pagination_is_just_empty( #[async_test] async fn test_pinned_timeline_with_pinned_utd_on_sync_contains_it() { - let test_helper = TestHelper::new().await; - let room_id = test_helper.room_id.clone(); + let server = MatrixMockServer::new().await; + let client = server.client_builder().build().await; + let room_id = room_id!("!test:localhost"); let event_id = event_id!("$1:morpheus.localhost"); let sender_id = owned_user_id!("@example:localhost"); - // Join the room - let joined_room_builder = JoinedRoomBuilder::new(&room_id) - // Set up encryption - .add_state_event(StateTestEvent::Encryption) - // And pinned event ids - .add_state_event(StateTestEvent::Custom(json!( - { - "content": { - "pinned": [event_id] - }, - "event_id": "$15139375513VdeRF:localhost", - "origin_server_ts": 151393755, - "sender": sender_id, - "state_key": "", - "type": "m.room.pinned_events", - "unsigned": { - "age": 703422 - } - } - ))); - - // Sync the joined room - test_helper - .server - .mock_sync() - .ok_and_run(&test_helper.client, move |sync_builder| { - sync_builder.add_joined_room(joined_room_builder); - }) - .await; + // Sync the joined room with a pinned event id + let room = PinnedEventsSync::new(room_id) + .with_pinned_event_ids(vec![event_id.as_str()]) + .mock_and_sync(&client, &server) + .await + .expect("Sync failed"); // Mock encrypted pinned event for which we don't have keys (an UTD) - let utd_event = create_utd(&room_id, &sender_id, event_id); - test_helper - .server - .mock_room_event() - .match_event_id() - .ok(TimelineEvent::new(utd_event)) - .mock_once() - .mount() - .await; + let utd_event = create_utd(room_id, &sender_id, event_id); + mock_events_endpoint(&server, room_id, vec![utd_event]).await; - let room = test_helper.client.get_room(&room_id).unwrap(); let timeline = Timeline::builder(&room).with_focus(pinned_events_focus(1)).build().await.unwrap(); @@ -515,27 +475,27 @@ async fn test_pinned_timeline_with_pinned_utd_on_sync_contains_it() { #[async_test] async fn test_edited_events_are_reflected_in_sync() { - let mut test_helper = TestHelper::new().await; - let room_id = test_helper.room_id.clone(); + let server = MatrixMockServer::new().await; + let client = server.client_builder().build().await; + let room_id = room_id!("!test:localhost"); - // Join the room - test_helper.do_initial_sync().await; - - let f = EventFactory::new().room(&room_id).sender(*BOB); + let f = EventFactory::new().room(room_id).sender(*BOB); let pinned_event = f .text_msg("in the end") .event_id(event_id!("$1")) .server_ts(MilliSecondsSinceUnixEpoch::now()) - .into_timeline(); + .into_raw_sync(); // Mock /event for some timeline events - test_helper.mock_events(vec![pinned_event]).await; + mock_events_endpoint(&server, room_id, vec![pinned_event]).await; // Load initial timeline items: a text message and a `m.room.pinned_events` with // event $1 - test_helper.sync_once(Vec::new(), Some(vec!["$1"])).await.expect("Sync failed"); - - let room = test_helper.client.get_room(&room_id).unwrap(); + let room = PinnedEventsSync::new(room_id) + .with_pinned_event_ids(vec!["$1"]) + .mock_and_sync(&client, &server) + .await + .expect("Sync failed"); let timeline = Timeline::builder(&room).with_focus(pinned_events_focus(100)).build().await.unwrap(); @@ -560,13 +520,17 @@ async fn test_edited_events_are_reflected_in_sync() { ) .event_id(event_id!("$2")) .server_ts(MilliSecondsSinceUnixEpoch::now()) - .into_timeline(); + .into_raw_sync(); // Mock /event for some timeline events - test_helper.mock_events(vec![edited_event.clone()]).await; + mock_events_endpoint(&server, room_id, vec![edited_event.clone()]).await; // Load new pinned event contents from sync, where $2 is and edit on $1 - test_helper.sync_once(vec![edited_event], None).await.expect("Sync failed"); + let _ = PinnedEventsSync::new(room_id) + .with_timeline_events(vec![edited_event]) + .mock_and_sync(&client, &server) + .await + .expect("Sync failed"); // The list is reloaded, so it's reset assert_next_matches_with_timeout!(timeline_stream, VectorDiff::Clear); @@ -593,27 +557,27 @@ async fn test_edited_events_are_reflected_in_sync() { #[async_test] async fn test_redacted_events_are_reflected_in_sync() { - let mut test_helper = TestHelper::new().await; - let room_id = test_helper.room_id.clone(); + let server = MatrixMockServer::new().await; + let client = server.client_builder().build().await; + let room_id = room_id!("!test:localhost"); - // Join the room - test_helper.do_initial_sync().await; - - let f = EventFactory::new().room(&room_id).sender(*BOB); + let f = EventFactory::new().room(room_id).sender(*BOB); let pinned_event = f .text_msg("in the end") .event_id(event_id!("$1")) .server_ts(MilliSecondsSinceUnixEpoch::now()) - .into_timeline(); + .into_raw_sync(); // Mock /event for some timeline events - test_helper.mock_events(vec![pinned_event]).await; + mock_events_endpoint(&server, room_id, vec![pinned_event]).await; // Load initial timeline items: a text message and a `m.room.pinned_events` with // event $1 - test_helper.sync_once(Vec::new(), Some(vec!["$1"])).await.expect("Sync failed"); - - let room = test_helper.client.get_room(&room_id).unwrap(); + let room = PinnedEventsSync::new(room_id) + .with_pinned_event_ids(vec!["$1"]) + .mock_and_sync(&client, &server) + .await + .expect("Sync failed"); let timeline = Timeline::builder(&room).with_focus(pinned_events_focus(100)).build().await.unwrap(); @@ -634,13 +598,17 @@ async fn test_redacted_events_are_reflected_in_sync() { .redaction(event_id!("$1")) .event_id(event_id!("$2")) .server_ts(MilliSecondsSinceUnixEpoch::now()) - .into_timeline(); + .into_raw_sync(); // Mock /event for some timeline events - test_helper.mock_events(vec![redaction_event.clone()]).await; + mock_events_endpoint(&server, room_id, vec![redaction_event.clone()]).await; // Load new pinned event contents from sync, where $1 is now redacted - let _ = test_helper.sync_once(vec![redaction_event], None).await; + let _ = PinnedEventsSync::new(room_id) + .with_timeline_events(vec![redaction_event]) + .mock_and_sync(&client, &server) + .await + .expect("Sync failed"); // The list is reloaded, so it's reset assert_next_matches_with_timeout!(timeline_stream, VectorDiff::Clear); @@ -662,26 +630,26 @@ async fn test_redacted_events_are_reflected_in_sync() { #[async_test] async fn test_edited_events_survive_pinned_event_ids_change() { - let mut test_helper = TestHelper::new().await; - let room_id = test_helper.room_id.clone(); + let server = MatrixMockServer::new().await; + let client = server.client_builder().build().await; + let room_id = room_id!("!test:localhost"); - // Join the room - test_helper.do_initial_sync().await; - - let f = EventFactory::new().room(&room_id).sender(*BOB); + let f = EventFactory::new().room(room_id).sender(*BOB); let pinned_event = f .text_msg("in the end") .event_id(event_id!("$1")) .server_ts(MilliSecondsSinceUnixEpoch::now()) - .into_timeline(); + .into_raw_sync(); // Mock /event for some timeline events - test_helper.mock_events(vec![pinned_event]).await; + mock_events_endpoint(&server, room_id, vec![pinned_event]).await; // Load initial timeline items: a `m.room.pinned_events` with event $1 pinned - test_helper.sync_once(Vec::new(), Some(vec!["$1"])).await.expect("Sync failed"); - - let room = test_helper.client.get_room(&room_id).unwrap(); + let room = PinnedEventsSync::new(room_id) + .with_pinned_event_ids(vec!["$1"]) + .mock_and_sync(&client, &server) + .await + .expect("Sync failed"); let timeline = Timeline::builder(&room).with_focus(pinned_events_focus(100)).build().await.unwrap(); @@ -706,14 +674,18 @@ async fn test_edited_events_survive_pinned_event_ids_change() { ) .event_id(event_id!("$2")) .server_ts(MilliSecondsSinceUnixEpoch::now()) - .into_timeline(); + .into_raw_sync(); // Mock /event for some timeline events - test_helper.mock_events(vec![edited_pinned_event.clone()]).await; + mock_events_endpoint(&server, room_id, vec![edited_pinned_event.clone()]).await; // Load new pinned event contents from sync, $2 was pinned but wasn't available // before - test_helper.sync_once(vec![edited_pinned_event], None).await.expect("Sync failed"); + let _ = PinnedEventsSync::new(room_id) + .with_timeline_events(vec![edited_pinned_event]) + .mock_and_sync(&client, &server) + .await + .expect("Sync failed"); // The list is reloaded, so it's reset assert_next_matches_with_timeout!(timeline_stream, VectorDiff::Clear); @@ -741,14 +713,16 @@ async fn test_edited_events_survive_pinned_event_ids_change() { .text_msg("new message") .event_id(event_id!("$3")) .server_ts(MilliSecondsSinceUnixEpoch::now()) - .into_timeline(); + .into_raw_sync(); // Mock /event for some timeline events - test_helper.mock_events(vec![new_pinned_event.clone()]).await; + mock_events_endpoint(&server, room_id, vec![new_pinned_event.clone()]).await; // Load new pinned event contents from sync: $3 - test_helper - .sync_once(vec![new_pinned_event], Some(vec!["$1", "$3"])) + let _ = PinnedEventsSync::new(room_id) + .with_timeline_events(vec![new_pinned_event]) + .with_pinned_event_ids(vec!["$1", "$3"]) + .mock_and_sync(&client, &server) .await .expect("Sync failed"); @@ -858,88 +832,86 @@ async fn test_ensure_max_concurrency_is_observed() { server.verify().await; } -struct TestHelper { - pub client: Client, - pub server: MatrixMockServer, - pub room_id: OwnedRoomId, +async fn mock_events_endpoint( + server: &MatrixMockServer, + room_id: &RoomId, + events: Vec>, +) { + for event in events { + server + .mock_room_event() + .room(room_id.to_owned()) + .match_event_id() + .ok(TimelineEvent::new(event.cast())) + .mount() + .await; + } } -impl TestHelper { - async fn new() -> Self { - let server = MatrixMockServer::new().await; - let client = server.client_builder().build().await; - Self { client, server, room_id: owned_room_id!("!a98sd12bjh:example.org") } +/// Allows to mock and sync a room adding optional timeline events and pinned +/// event ids +#[derive(Debug, Clone)] +struct PinnedEventsSync { + room_id: OwnedRoomId, + timeline_events: Vec>, + pinned_event_ids: Option>, +} + +impl PinnedEventsSync { + fn new(room_id: &RoomId) -> Self { + Self { room_id: room_id.to_owned(), timeline_events: Vec::new(), pinned_event_ids: None } } - async fn do_initial_sync(&mut self) { - let joined_room_builder = JoinedRoomBuilder::new(&self.room_id) + fn with_timeline_events(mut self, items: Vec>) -> Self { + self.timeline_events = items; + self + } + + fn with_pinned_event_ids(mut self, pinned_event_ids: Vec<&str>) -> Self { + let pinned_event_ids: Vec = pinned_event_ids + .into_iter() + .map(|id| match EventId::parse(id) { + Ok(id) => id, + Err(_) => panic!("Invalid event id: {}", id), + }) + .collect(); + + self.pinned_event_ids = Some(pinned_event_ids); + self + } + + async fn mock_and_sync( + self, + client: &Client, + server: &MatrixMockServer, + ) -> Result { + let mut joined_room_builder = JoinedRoomBuilder::new(&self.room_id) // Set up encryption .add_state_event(StateTestEvent::Encryption); - self.server - .mock_sync() - .ok_and_run(&self.client, move |sync_builder| { - // Mark the room as joined. - sync_builder.add_joined_room(joined_room_builder); - }) - .await; - } + joined_room_builder = joined_room_builder.add_timeline_bulk(self.timeline_events); - async fn mock_events(&mut self, events: Vec) { - for event in events { - self.server - .mock_room_event() - .room(self.room_id.to_owned()) - .match_event_id() - .ok(event) - .mount() - .await; - } - } + if let Some(pinned_event_ids) = self.pinned_event_ids { + let pinned_events_event = EventFactory::new() + .room(&self.room_id) + .event(RoomPinnedEventsEventContent::new(pinned_event_ids)) + .sender(user_id!("@example:localhost")) + .state_key("") + .into_raw_sync(); - async fn sync_once( - &mut self, - timeline_events: Vec, - pinned_event_ids: Option>, - ) -> Result<(), matrix_sdk::Error> { - let mut joined_room_builder = JoinedRoomBuilder::new(&self.room_id); - for timeline_event in timeline_events { - joined_room_builder = joined_room_builder.add_timeline_event(timeline_event.into_raw()); - } - - if let Some(pinned_event_ids) = pinned_event_ids { - let pinned_event_ids: Vec = - pinned_event_ids.into_iter().map(|id| id.to_owned()).collect(); joined_room_builder = - joined_room_builder.add_state_event(StateTestEvent::Custom(json!( - { - "content": { - "pinned": pinned_event_ids - }, - "event_id": "$15139375513VdeRF:localhost", - "origin_server_ts": 151393755, - "sender": "@example:localhost", - "state_key": "", - "type": "m.room.pinned_events", - "unsigned": { - "age": 703422 - } - } - ))) + joined_room_builder.add_state_bulk(vec![pinned_events_event.cast()]); } - self.server - .mock_sync() - .ok_and_run(&self.client, move |sync_builder| { - sync_builder.add_joined_room(joined_room_builder); - }) - .await; - - Ok(()) + Ok(server.sync_room(client, joined_room_builder).await) } } -fn create_utd(room_id: &RoomId, sender_id: &UserId, event_id: &EventId) -> Raw { +fn create_utd( + room_id: &RoomId, + sender_id: &UserId, + event_id: &EventId, +) -> Raw { EventFactory::new() .room(room_id) .sender(sender_id) @@ -962,7 +934,7 @@ fn create_utd(room_id: &RoomId, sender_id: &UserId, event_id: &EventId) -> Raw TimelineFocus {