Skip to content

Commit 69588d5

Browse files
committed
test(timeline): use a builder pattern to create a TestTimeline
1 parent 7b77b19 commit 69588d5

File tree

7 files changed

+175
-155
lines changed

7 files changed

+175
-155
lines changed

crates/matrix-sdk-ui/src/timeline/tests/basic.rs

+15-11
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ use super::TestTimeline;
3939
use crate::timeline::{
4040
controller::TimelineSettings,
4141
event_item::{AnyOtherFullStateEventContent, RemoteEventOrigin},
42-
tests::{ReadReceiptMap, TestRoomDataProvider},
42+
tests::{ReadReceiptMap, TestRoomDataProvider, TestTimelineBuilder},
4343
MembershipChange, TimelineDetails, TimelineItemContent, TimelineItemKind, VirtualTimelineItem,
4444
};
4545

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

89-
let timeline = TestTimeline::with_room_data_provider(
90-
TestRoomDataProvider::default()
91-
// Also add a fully read marker.
92-
.with_fully_read_marker(event_id)
93-
.with_initial_user_receipts(receipts),
94-
)
95-
.with_settings(TimelineSettings { track_read_receipts: true, ..Default::default() });
89+
let timeline = TestTimelineBuilder::new()
90+
.provider(
91+
TestRoomDataProvider::default()
92+
// Also add a fully read marker.
93+
.with_fully_read_marker(event_id)
94+
.with_initial_user_receipts(receipts),
95+
)
96+
.settings(TimelineSettings { track_read_receipts: true, ..Default::default() })
97+
.build();
9698

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

280282
#[async_test]
281283
async fn test_internal_id_prefix() {
282-
let timeline = TestTimeline::with_internal_id_prefix("le_prefix_".to_owned());
284+
let timeline = TestTimelineBuilder::new().internal_id_prefix("le_prefix_".to_owned()).build();
283285

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

448450
#[async_test]
449451
async fn test_replace_with_initial_events_when_batched() {
450-
let timeline = TestTimeline::with_room_data_provider(TestRoomDataProvider::default())
451-
.with_settings(TimelineSettings::default());
452+
let timeline = TestTimelineBuilder::new()
453+
.provider(TestRoomDataProvider::default())
454+
.settings(TimelineSettings::default())
455+
.build();
452456

453457
let f = &timeline.factory;
454458
let ev = f.text_msg("hey").sender(*ALICE).into_event();

crates/matrix-sdk-ui/src/timeline/tests/echo.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use super::TestTimeline;
3030
use crate::timeline::{
3131
controller::TimelineSettings,
3232
event_item::{EventSendState, RemoteEventOrigin},
33-
tests::TestRoomDataProvider,
33+
tests::{TestRoomDataProvider, TestTimelineBuilder},
3434
};
3535

3636
#[async_test]
@@ -235,10 +235,10 @@ async fn test_date_divider_removed_after_local_echo_disappeared() {
235235
async fn test_no_read_marker_with_local_echo() {
236236
let event_id = event_id!("$1");
237237

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

243243
let f = &timeline.factory;
244244

crates/matrix-sdk-ui/src/timeline/tests/encryption.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ use tokio::time::sleep;
4848

4949
use super::TestTimeline;
5050
use crate::{
51-
timeline::{EncryptedMessage, TimelineDetails, TimelineItemContent},
51+
timeline::{
52+
tests::TestTimelineBuilder, EncryptedMessage, TimelineDetails, TimelineItemContent,
53+
},
5254
unable_to_decrypt_hook::{UnableToDecryptHook, UnableToDecryptInfo, UtdHookManager},
5355
};
5456

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

87-
let timeline = TestTimeline::with_unable_to_decrypt_hook(utd_hook.clone());
89+
let timeline = TestTimelineBuilder::new().unable_to_decrypt_hook(utd_hook.clone()).build();
8890
let mut stream = timeline.subscribe().await;
8991

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

188-
let timeline = TestTimeline::with_unable_to_decrypt_hook(utd_hook.clone());
190+
let timeline = TestTimelineBuilder::new().unable_to_decrypt_hook(utd_hook.clone()).build();
189191

190192
let f = &timeline.factory;
191193
timeline

crates/matrix-sdk-ui/src/timeline/tests/event_filter.rs

+26-20
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ use stream_assert::assert_next_matches;
3030

3131
use super::TestTimeline;
3232
use crate::timeline::{
33-
controller::TimelineSettings, AnyOtherFullStateEventContent, TimelineEventTypeFilter,
34-
TimelineItem, TimelineItemContent, TimelineItemKind,
33+
controller::TimelineSettings, tests::TestTimelineBuilder, AnyOtherFullStateEventContent,
34+
TimelineEventTypeFilter, TimelineItem, TimelineItemContent, TimelineItemKind,
3535
};
3636

3737
#[async_test]
@@ -92,10 +92,9 @@ async fn test_default_filter() {
9292

9393
#[async_test]
9494
async fn test_filter_always_false() {
95-
let timeline = TestTimeline::new().with_settings(TimelineSettings {
96-
event_filter: Arc::new(|_, _| false),
97-
..Default::default()
98-
});
95+
let timeline = TestTimelineBuilder::new()
96+
.settings(TimelineSettings { event_filter: Arc::new(|_, _| false), ..Default::default() })
97+
.build();
9998

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

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

136137
#[async_test]
137138
async fn test_hide_failed_to_parse() {
138-
let timeline = TestTimeline::new()
139-
.with_settings(TimelineSettings { add_failed_to_parse: false, ..Default::default() });
139+
let timeline = TestTimelineBuilder::new()
140+
.settings(TimelineSettings { add_failed_to_parse: false, ..Default::default() })
141+
.build();
140142

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

174-
let timeline = TestTimeline::new().with_settings(TimelineSettings {
175-
event_filter: Arc::new(move |event, _| event_filter.filter(event)),
176-
..Default::default()
177-
});
176+
let timeline = TestTimelineBuilder::new()
177+
.settings(TimelineSettings {
178+
event_filter: Arc::new(move |event, _| event_filter.filter(event)),
179+
..Default::default()
180+
})
181+
.build();
178182
let f = &timeline.factory;
179183

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

204-
let timeline = TestTimeline::new().with_settings(TimelineSettings {
205-
event_filter: Arc::new(move |event, _| event_filter.filter(event)),
206-
..Default::default()
207-
});
208+
let timeline = TestTimelineBuilder::new()
209+
.settings(TimelineSettings {
210+
event_filter: Arc::new(move |event, _| event_filter.filter(event)),
211+
..Default::default()
212+
})
213+
.build();
208214
let f = &timeline.factory;
209215

210216
// Add a message event

crates/matrix-sdk-ui/src/timeline/tests/mod.rs

+56-58
Original file line numberDiff line numberDiff line change
@@ -79,80 +79,78 @@ mod shields;
7979
mod virt;
8080

8181
/// A timeline instance used only for testing purposes in unit tests.
82-
struct TestTimeline {
83-
controller: TimelineController<TestRoomDataProvider>,
84-
85-
/// An [`EventFactory`] that can be used for creating events in this
86-
/// timeline.
87-
pub factory: EventFactory,
82+
#[derive(Default)]
83+
struct TestTimelineBuilder {
84+
provider: Option<TestRoomDataProvider>,
85+
internal_id_prefix: Option<String>,
86+
utd_hook: Option<Arc<UtdHookManager>>,
87+
is_room_encrypted: bool,
88+
settings: Option<TimelineSettings>,
8889
}
8990

90-
impl TestTimeline {
91+
impl TestTimelineBuilder {
9192
fn new() -> Self {
92-
Self::with_room_data_provider(TestRoomDataProvider::default())
93+
Self::default()
9394
}
9495

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

100-
fn with_internal_id_prefix(prefix: String) -> Self {
101-
Self {
102-
controller: TimelineController::new(
103-
TestRoomDataProvider::default(),
104-
TimelineFocus::Live,
105-
Some(prefix),
106-
None,
107-
false,
108-
),
109-
factory: EventFactory::new(),
110-
}
101+
fn internal_id_prefix(mut self, prefix: String) -> Self {
102+
self.internal_id_prefix = Some(prefix);
103+
self
111104
}
112105

113-
fn with_room_data_provider(room_data_provider: TestRoomDataProvider) -> Self {
114-
Self {
115-
controller: TimelineController::new(
116-
room_data_provider,
117-
TimelineFocus::Live,
118-
None,
119-
None,
120-
false,
121-
),
122-
factory: EventFactory::new(),
123-
}
106+
fn unable_to_decrypt_hook(mut self, hook: Arc<UtdHookManager>) -> Self {
107+
self.utd_hook = Some(hook);
108+
// It only makes sense to have a UTD hook for an encrypted room.
109+
self.is_room_encrypted = true;
110+
self
124111
}
125112

126-
fn with_unable_to_decrypt_hook(hook: Arc<UtdHookManager>) -> Self {
127-
Self {
128-
controller: TimelineController::new(
129-
TestRoomDataProvider::default(),
130-
TimelineFocus::Live,
131-
None,
132-
Some(hook),
133-
true,
134-
),
135-
factory: EventFactory::new(),
136-
}
113+
fn room_encrypted(mut self, encrypted: bool) -> Self {
114+
self.is_room_encrypted = encrypted;
115+
self
137116
}
138117

139-
// TODO: this is wrong, see also #3850.
140-
fn with_is_room_encrypted(encrypted: bool) -> Self {
141-
Self {
142-
controller: TimelineController::new(
143-
TestRoomDataProvider::default(),
144-
TimelineFocus::Live,
145-
None,
146-
None,
147-
encrypted,
148-
),
149-
factory: EventFactory::new(),
118+
fn settings(mut self, settings: TimelineSettings) -> Self {
119+
self.settings = Some(settings);
120+
self
121+
}
122+
123+
fn build(self) -> TestTimeline {
124+
let mut controller = TimelineController::new(
125+
self.provider.unwrap_or_default(),
126+
TimelineFocus::Live,
127+
self.internal_id_prefix,
128+
self.utd_hook,
129+
self.is_room_encrypted,
130+
);
131+
if let Some(settings) = self.settings {
132+
controller = controller.with_settings(settings);
150133
}
134+
TestTimeline { controller, factory: EventFactory::new() }
151135
}
136+
}
152137

153-
fn with_settings(mut self, settings: TimelineSettings) -> Self {
154-
self.controller = self.controller.with_settings(settings);
155-
self
138+
struct TestTimeline {
139+
controller: TimelineController<TestRoomDataProvider>,
140+
141+
/// An [`EventFactory`] that can be used for creating events in this
142+
/// timeline.
143+
pub factory: EventFactory,
144+
}
145+
146+
impl TestTimeline {
147+
fn new() -> Self {
148+
TestTimelineBuilder::new().build()
149+
}
150+
151+
/// Returns the associated inner data from that [`TestTimeline`].
152+
fn data(&self) -> &TestRoomDataProvider {
153+
&self.controller.room_data_provider
156154
}
157155

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

0 commit comments

Comments
 (0)