Skip to content

Commit

Permalink
test(timeline): use a builder pattern to create a TestTimeline
Browse files Browse the repository at this point in the history
  • Loading branch information
bnjbvr committed Feb 6, 2025
1 parent a073324 commit 94575db
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 154 deletions.
26 changes: 15 additions & 11 deletions crates/matrix-sdk-ui/src/timeline/tests/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ use super::TestTimeline;
use crate::timeline::{
controller::TimelineSettings,
event_item::{AnyOtherFullStateEventContent, RemoteEventOrigin},
tests::{ReadReceiptMap, TestRoomDataProvider},
tests::{ReadReceiptMap, TestRoomDataProvider, TestTimelineBuilder},
MembershipChange, TimelineDetails, TimelineItemContent, TimelineItemKind, VirtualTimelineItem,
};

Expand Down Expand Up @@ -86,13 +86,15 @@ async fn test_replace_with_initial_events_and_read_marker() {
.entry(ALICE.to_owned())
.or_insert_with(|| (event_id.to_owned(), Receipt::new(MilliSecondsSinceUnixEpoch::now())));

let timeline = TestTimeline::with_room_data_provider(
TestRoomDataProvider::default()
// Also add a fully read marker.
.with_fully_read_marker(event_id)
.with_initial_user_receipts(receipts),
)
.with_settings(TimelineSettings { track_read_receipts: true, ..Default::default() });
let timeline = TestTimelineBuilder::new()
.provider(
TestRoomDataProvider::default()
// Also add a fully read marker.
.with_fully_read_marker(event_id)
.with_initial_user_receipts(receipts),
)
.settings(TimelineSettings { track_read_receipts: true, ..Default::default() })
.build();

let f = &timeline.factory;
let ev = f.text_msg("hey").sender(*ALICE).into_event();
Expand Down Expand Up @@ -279,7 +281,7 @@ async fn test_other_state() {

#[async_test]
async fn test_internal_id_prefix() {
let timeline = TestTimeline::with_internal_id_prefix("le_prefix_".to_owned());
let timeline = TestTimelineBuilder::new().internal_id_prefix("le_prefix_".to_owned()).build();

let f = &timeline.factory;
let ev_a = f.text_msg("A").sender(*ALICE).into_event();
Expand Down Expand Up @@ -447,8 +449,10 @@ async fn test_thread() {

#[async_test]
async fn test_replace_with_initial_events_when_batched() {
let timeline = TestTimeline::with_room_data_provider(TestRoomDataProvider::default())
.with_settings(TimelineSettings::default());
let timeline = TestTimelineBuilder::new()
.provider(TestRoomDataProvider::default())
.settings(TimelineSettings::default())
.build();

let f = &timeline.factory;
let ev = f.text_msg("hey").sender(*ALICE).into_event();
Expand Down
10 changes: 5 additions & 5 deletions crates/matrix-sdk-ui/src/timeline/tests/echo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use super::TestTimeline;
use crate::timeline::{
controller::TimelineSettings,
event_item::{EventSendState, RemoteEventOrigin},
tests::TestRoomDataProvider,
tests::{TestRoomDataProvider, TestTimelineBuilder},
};

#[async_test]
Expand Down Expand Up @@ -235,10 +235,10 @@ async fn test_date_divider_removed_after_local_echo_disappeared() {
async fn test_no_read_marker_with_local_echo() {
let event_id = event_id!("$1");

let timeline = TestTimeline::with_room_data_provider(
TestRoomDataProvider::default().with_fully_read_marker(event_id.to_owned()),
)
.with_settings(TimelineSettings { track_read_receipts: true, ..Default::default() });
let timeline = TestTimelineBuilder::new()
.provider(TestRoomDataProvider::default().with_fully_read_marker(event_id.to_owned()))
.settings(TimelineSettings { track_read_receipts: true, ..Default::default() })
.build();

let f = &timeline.factory;

Expand Down
8 changes: 5 additions & 3 deletions crates/matrix-sdk-ui/src/timeline/tests/encryption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ use tokio::time::sleep;

use super::TestTimeline;
use crate::{
timeline::{EncryptedMessage, TimelineDetails, TimelineItemContent},
timeline::{
tests::TestTimelineBuilder, EncryptedMessage, TimelineDetails, TimelineItemContent,
},
unable_to_decrypt_hook::{UnableToDecryptHook, UnableToDecryptInfo, UtdHookManager},
};

Expand Down Expand Up @@ -84,7 +86,7 @@ async fn test_retry_message_decryption() {
let client = test_client_builder(None).build().await.unwrap();
let utd_hook = Arc::new(UtdHookManager::new(hook.clone(), client));

let timeline = TestTimeline::with_unable_to_decrypt_hook(utd_hook.clone());
let timeline = TestTimelineBuilder::new().unable_to_decrypt_hook(utd_hook.clone()).build();
let mut stream = timeline.subscribe().await;

let f = &timeline.factory;
Expand Down Expand Up @@ -185,7 +187,7 @@ async fn test_false_positive_late_decryption_regression() {
let utd_hook =
Arc::new(UtdHookManager::new(hook.clone(), client).with_max_delay(Duration::from_secs(1)));

let timeline = TestTimeline::with_unable_to_decrypt_hook(utd_hook.clone());
let timeline = TestTimelineBuilder::new().unable_to_decrypt_hook(utd_hook.clone()).build();

let f = &timeline.factory;
timeline
Expand Down
46 changes: 26 additions & 20 deletions crates/matrix-sdk-ui/src/timeline/tests/event_filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ use stream_assert::assert_next_matches;

use super::TestTimeline;
use crate::timeline::{
controller::TimelineSettings, AnyOtherFullStateEventContent, TimelineEventTypeFilter,
TimelineItem, TimelineItemContent, TimelineItemKind,
controller::TimelineSettings, tests::TestTimelineBuilder, AnyOtherFullStateEventContent,
TimelineEventTypeFilter, TimelineItem, TimelineItemContent, TimelineItemKind,
};

#[async_test]
Expand Down Expand Up @@ -92,10 +92,9 @@ async fn test_default_filter() {

#[async_test]
async fn test_filter_always_false() {
let timeline = TestTimeline::new().with_settings(TimelineSettings {
event_filter: Arc::new(|_, _| false),
..Default::default()
});
let timeline = TestTimelineBuilder::new()
.settings(TimelineSettings { event_filter: Arc::new(|_, _| false), ..Default::default() })
.build();

let f = &timeline.factory;
timeline.handle_live_event(f.text_msg("The first message").sender(&ALICE)).await;
Expand All @@ -112,10 +111,12 @@ async fn test_filter_always_false() {
#[async_test]
async fn test_custom_filter() {
// Filter out all state events.
let timeline = TestTimeline::new().with_settings(TimelineSettings {
event_filter: Arc::new(|ev, _| matches!(ev, AnySyncTimelineEvent::MessageLike(_))),
..Default::default()
});
let timeline = TestTimelineBuilder::new()
.settings(TimelineSettings {
event_filter: Arc::new(|ev, _| matches!(ev, AnySyncTimelineEvent::MessageLike(_))),
..Default::default()
})
.build();
let mut stream = timeline.subscribe().await;

let f = &timeline.factory;
Expand All @@ -135,8 +136,9 @@ async fn test_custom_filter() {

#[async_test]
async fn test_hide_failed_to_parse() {
let timeline = TestTimeline::new()
.with_settings(TimelineSettings { add_failed_to_parse: false, ..Default::default() });
let timeline = TestTimelineBuilder::new()
.settings(TimelineSettings { add_failed_to_parse: false, ..Default::default() })
.build();

// m.room.message events must have a msgtype and body in content, so this
// event with an empty content object should fail to deserialize.
Expand Down Expand Up @@ -171,10 +173,12 @@ async fn test_event_type_filter_include_only_room_names() {
// Only return room name events
let event_filter = TimelineEventTypeFilter::Include(vec![TimelineEventType::RoomName]);

let timeline = TestTimeline::new().with_settings(TimelineSettings {
event_filter: Arc::new(move |event, _| event_filter.filter(event)),
..Default::default()
});
let timeline = TestTimelineBuilder::new()
.settings(TimelineSettings {
event_filter: Arc::new(move |event, _| event_filter.filter(event)),
..Default::default()
})
.build();
let f = &timeline.factory;

// Add a non-encrypted message event
Expand All @@ -201,10 +205,12 @@ async fn test_event_type_filter_exclude_messages() {
// Don't return any messages
let event_filter = TimelineEventTypeFilter::Exclude(vec![TimelineEventType::RoomMessage]);

let timeline = TestTimeline::new().with_settings(TimelineSettings {
event_filter: Arc::new(move |event, _| event_filter.filter(event)),
..Default::default()
});
let timeline = TestTimelineBuilder::new()
.settings(TimelineSettings {
event_filter: Arc::new(move |event, _| event_filter.filter(event)),
..Default::default()
})
.build();
let f = &timeline.factory;

// Add a message event
Expand Down
112 changes: 55 additions & 57 deletions crates/matrix-sdk-ui/src/timeline/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,79 +78,77 @@ mod redaction;
mod shields;
mod virt;

struct TestTimeline {
controller: TimelineController<TestRoomDataProvider>,
/// An [`EventFactory`] that can be used for creating events in this
/// timeline.
pub factory: EventFactory,
#[derive(Default)]
struct TestTimelineBuilder {
provider: Option<TestRoomDataProvider>,
internal_id_prefix: Option<String>,
utd_hook: Option<Arc<UtdHookManager>>,
is_room_encrypted: bool,
settings: Option<TimelineSettings>,
}

impl TestTimeline {
impl TestTimelineBuilder {
fn new() -> Self {
Self::with_room_data_provider(TestRoomDataProvider::default())
Self::default()
}

/// Returns the associated inner data from that [`TestTimeline`].
fn data(&self) -> &TestRoomDataProvider {
&self.controller.room_data_provider
fn provider(mut self, provider: TestRoomDataProvider) -> Self {
self.provider = Some(provider);
self
}

fn with_internal_id_prefix(prefix: String) -> Self {
Self {
controller: TimelineController::new(
TestRoomDataProvider::default(),
TimelineFocus::Live,
Some(prefix),
None,
false,
),
factory: EventFactory::new(),
}
fn internal_id_prefix(mut self, prefix: String) -> Self {
self.internal_id_prefix = Some(prefix);
self
}

fn with_room_data_provider(room_data_provider: TestRoomDataProvider) -> Self {
Self {
controller: TimelineController::new(
room_data_provider,
TimelineFocus::Live,
None,
None,
false,
),
factory: EventFactory::new(),
}
fn unable_to_decrypt_hook(mut self, hook: Arc<UtdHookManager>) -> Self {
self.utd_hook = Some(hook);
// It only makes sense to have a UTD hook for an encrypted room.
self.is_room_encrypted = true;
self
}

fn with_unable_to_decrypt_hook(hook: Arc<UtdHookManager>) -> Self {
Self {
controller: TimelineController::new(
TestRoomDataProvider::default(),
TimelineFocus::Live,
None,
Some(hook),
true,
),
factory: EventFactory::new(),
}
fn is_room_encrypted(mut self, encrypted: bool) -> Self {
self.is_room_encrypted = encrypted;
self
}

// TODO: this is wrong, see also #3850.
fn with_is_room_encrypted(encrypted: bool) -> Self {
Self {
controller: TimelineController::new(
TestRoomDataProvider::default(),
TimelineFocus::Live,
None,
None,
encrypted,
),
factory: EventFactory::new(),
fn settings(mut self, settings: TimelineSettings) -> Self {
self.settings = Some(settings);
self
}

fn build(self) -> TestTimeline {
let mut controller = TimelineController::new(
self.provider.unwrap_or_default(),
TimelineFocus::Live,
self.internal_id_prefix,
self.utd_hook,
self.is_room_encrypted,
);
if let Some(settings) = self.settings {
controller = controller.with_settings(settings);
}
TestTimeline { controller, factory: EventFactory::new() }
}
}

fn with_settings(mut self, settings: TimelineSettings) -> Self {
self.controller = self.controller.with_settings(settings);
self
struct TestTimeline {
controller: TimelineController<TestRoomDataProvider>,
/// An [`EventFactory`] that can be used for creating events in this
/// timeline.
pub factory: EventFactory,
}

impl TestTimeline {
fn new() -> Self {
TestTimelineBuilder::new().build()
}

/// Returns the associated inner data from that [`TestTimeline`].
fn data(&self) -> &TestRoomDataProvider {
&self.controller.room_data_provider
}

async fn subscribe(&self) -> impl Stream<Item = VectorDiff<Arc<TimelineItem>>> {
Expand Down
Loading

0 comments on commit 94575db

Please sign in to comment.