diff --git a/crates/matrix-sdk-ui/src/timeline/tests/event_filter.rs b/crates/matrix-sdk-ui/src/timeline/tests/event_filter.rs index d7a6db8fc..e135c33e9 100644 --- a/crates/matrix-sdk-ui/src/timeline/tests/event_filter.rs +++ b/crates/matrix-sdk-ui/src/timeline/tests/event_filter.rs @@ -17,6 +17,7 @@ use std::sync::Arc; use assert_matches::assert_matches; use assert_matches2::assert_let; use eyeball_im::VectorDiff; +use matrix_sdk::test_utils::events::EventFactory; use matrix_sdk_test::{async_test, sync_timeline_event, ALICE, BOB}; use ruma::{ assign, @@ -47,10 +48,11 @@ async fn test_default_filter() { let timeline = TestTimeline::new(); let mut stream = timeline.subscribe().await; + let f = EventFactory::new(); + // Test edits work. - timeline - .handle_live_message_event(&ALICE, RoomMessageEventContent::text_plain("The first message")) - .await; + timeline.handle_live_event(f.text_msg("The first message").sender(&ALICE)).await; + let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); let _day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); let first_event_id = item.as_event().unwrap().event_id().unwrap(); @@ -72,31 +74,24 @@ async fn test_default_filter() { // TODO: After adding raw timeline items, check for one here. // Test redactions work. - timeline - .handle_live_message_event( - &ALICE, - RoomMessageEventContent::text_plain("The second message"), - ) - .await; + timeline.handle_live_event(f.text_msg("The second message").sender(&ALICE)).await; let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); let second_event_id = item.as_event().unwrap().event_id().unwrap(); - timeline.handle_live_redaction(&BOB, second_event_id).await; + timeline.handle_live_event(f.redaction(second_event_id).sender(&BOB)).await; let item = assert_next_matches!(stream, VectorDiff::Set { index: 2, value } => value); assert_matches!(item.as_event().unwrap().content(), TimelineItemContent::RedactedMessage); // TODO: After adding raw timeline items, check for one here. // Test reactions work. - timeline - .handle_live_message_event(&ALICE, RoomMessageEventContent::text_plain("The third message")) - .await; + timeline.handle_live_event(f.text_msg("The third message").sender(&ALICE)).await; let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); let third_event_id = item.as_event().unwrap().event_id().unwrap(); let rel = Annotation::new(third_event_id.to_owned(), "+1".to_owned()); timeline.handle_live_message_event(&BOB, ReactionEventContent::new(rel)).await; - timeline.handle_live_redaction(&BOB, second_event_id).await; + timeline.handle_live_event(f.redaction(second_event_id).sender(&BOB)).await; let item = assert_next_matches!(stream, VectorDiff::Set { index: 3, value } => value); assert_eq!(item.as_event().unwrap().reactions().len(), 1); diff --git a/crates/matrix-sdk-ui/src/timeline/tests/mod.rs b/crates/matrix-sdk-ui/src/timeline/tests/mod.rs index e5e5d0ade..687c85709 100644 --- a/crates/matrix-sdk-ui/src/timeline/tests/mod.rs +++ b/crates/matrix-sdk-ui/src/timeline/tests/mod.rs @@ -37,9 +37,8 @@ use ruma::{ events::{ receipt::{Receipt, ReceiptThread, ReceiptType}, relation::Annotation, - AnyMessageLikeEventContent, AnySyncTimelineEvent, AnyTimelineEvent, EmptyStateKey, - MessageLikeEventContent, RedactedMessageLikeEventContent, RedactedStateEventContent, - StaticStateEventContent, + AnyMessageLikeEventContent, AnyTimelineEvent, EmptyStateKey, MessageLikeEventContent, + RedactedMessageLikeEventContent, RedactedStateEventContent, StaticStateEventContent, }, int, power_levels::NotificationPowerLevels, @@ -212,11 +211,6 @@ impl TestTimeline { self.handle_live_event(Raw::new(&ev).unwrap().cast()).await; } - async fn handle_live_redaction(&self, sender: &UserId, redacts: &EventId) { - let ev = self.event_builder.make_redaction_event(sender, redacts); - self.handle_live_event(ev).await; - } - async fn handle_live_reaction(&self, sender: &UserId, annotation: &Annotation) -> OwnedEventId { let event_id = EventId::new(server_name!("dummy.server")); let ev = self.event_builder.make_reaction_event(sender, &event_id, annotation); @@ -224,8 +218,8 @@ impl TestTimeline { event_id } - async fn handle_live_event(&self, event: Raw) { - let event = SyncTimelineEvent::new(event); + async fn handle_live_event(&self, event: impl Into) { + let event = event.into(); self.inner.add_events_at(vec![event], TimelineEnd::Back, RemoteEventOrigin::Sync).await; } diff --git a/crates/matrix-sdk-ui/src/timeline/tests/redaction.rs b/crates/matrix-sdk-ui/src/timeline/tests/redaction.rs index 1d1d7f0ed..00e33a2df 100644 --- a/crates/matrix-sdk-ui/src/timeline/tests/redaction.rs +++ b/crates/matrix-sdk-ui/src/timeline/tests/redaction.rs @@ -15,12 +15,12 @@ use assert_matches::assert_matches; use assert_matches2::assert_let; use eyeball_im::VectorDiff; +use matrix_sdk::test_utils::events::EventFactory; use matrix_sdk_base::deserialized_responses::SyncTimelineEvent; -use matrix_sdk_test::{async_test, sync_timeline_event, ALICE, BOB}; +use matrix_sdk_test::{async_test, ALICE, BOB}; use ruma::{ events::{ - reaction::{ReactionEventContent, RedactedReactionEventContent}, - relation::Annotation, + reaction::RedactedReactionEventContent, room::{ message::{ AddMentions, ForwardThread, OriginalSyncRoomMessageEvent, @@ -45,6 +45,8 @@ async fn test_redact_state_event() { let timeline = TestTimeline::new(); let mut stream = timeline.subscribe_events().await; + let f = EventFactory::new(); + timeline .handle_live_state_event( &ALICE, @@ -60,7 +62,7 @@ async fn test_redact_state_event() { AnyOtherFullStateEventContent::RoomName(FullStateEventContent::Original { .. }) ); - timeline.handle_live_redaction(&ALICE, item.event_id().unwrap()).await; + timeline.handle_live_event(f.redaction(item.event_id().unwrap()).sender(&ALICE)).await; let item = assert_next_matches!(stream, VectorDiff::Set { index: 0, value } => value); assert_let!(TimelineItemContent::OtherState(state) = item.content()); @@ -75,9 +77,9 @@ async fn test_redact_replied_to_event() { let timeline = TestTimeline::new(); let mut stream = timeline.subscribe_events().await; - timeline - .handle_live_message_event(&ALICE, RoomMessageEventContent::text_plain("Hello, world!")) - .await; + let f = EventFactory::new(); + + timeline.handle_live_event(f.text_msg("Hello, world!").sender(&ALICE)).await; let first_item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); assert_matches!(first_item.content(), TimelineItemContent::Message(_)); @@ -101,7 +103,7 @@ async fn test_redact_replied_to_event() { assert_let!(TimelineDetails::Ready(replied_to_event) = &in_reply_to.event); assert_matches!(replied_to_event.content(), TimelineItemContent::Message(_)); - timeline.handle_live_redaction(&ALICE, first_item.event_id().unwrap()).await; + timeline.handle_live_event(f.redaction(first_item.event_id().unwrap()).sender(&ALICE)).await; let first_item_again = assert_next_matches!(stream, VectorDiff::Set { index: 0, value } => value); @@ -121,14 +123,15 @@ async fn test_reaction_redaction() { let timeline = TestTimeline::new(); let mut stream = timeline.subscribe_events().await; - timeline.handle_live_message_event(&ALICE, RoomMessageEventContent::text_plain("hi!")).await; + let f = EventFactory::new(); + + timeline.handle_live_event(f.text_msg("hi!").sender(&ALICE)).await; let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); assert_eq!(item.reactions().len(), 0); let msg_event_id = item.event_id().unwrap(); - let rel = Annotation::new(msg_event_id.to_owned(), "+1".to_owned()); - timeline.handle_live_message_event(&BOB, ReactionEventContent::new(rel)).await; + timeline.handle_live_event(f.reaction(msg_event_id, "+1".to_owned()).sender(&BOB)).await; let item = assert_next_matches!(stream, VectorDiff::Set { index: 0, value } => value); assert_eq!(item.reactions().len(), 1); @@ -136,7 +139,7 @@ async fn test_reaction_redaction() { let reaction_event_id = item.event_id().unwrap(); - timeline.handle_live_redaction(&BOB, reaction_event_id).await; + timeline.handle_live_event(f.redaction(reaction_event_id).sender(&BOB)).await; let item = assert_next_matches!(stream, VectorDiff::Set { index: 0, value } => value); assert_eq!(item.reactions().len(), 0); } @@ -146,6 +149,8 @@ async fn test_reaction_redaction_timeline_filter() { let timeline = TestTimeline::new(); let mut stream = timeline.subscribe_events().await; + let f = EventFactory::new(); + // Initialise a timeline with a redacted reaction. timeline .inner @@ -167,20 +172,21 @@ async fn test_reaction_redaction_timeline_filter() { assert_eq!(timeline.inner.items().await.len(), 0); // Adding a room message - timeline.handle_live_message_event(&ALICE, RoomMessageEventContent::text_plain("hi!")).await; + timeline.handle_live_event(f.text_msg("hi!").sender(&ALICE)).await; let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); // Creates a day divider and the message. assert_eq!(timeline.inner.items().await.len(), 2); // Reaction is attached to the message and doesn't add a timeline item. - let rel = Annotation::new(item.event_id().unwrap().to_owned(), "+1".to_owned()); - timeline.handle_live_message_event(&BOB, ReactionEventContent::new(rel)).await; + timeline + .handle_live_event(f.reaction(item.event_id().unwrap(), "+1".to_owned()).sender(&BOB)) + .await; let item = assert_next_matches!(stream, VectorDiff::Set { index: 0, value } => value); let reaction_event_id = item.event_id().unwrap(); assert_eq!(timeline.inner.items().await.len(), 2); // Redacting the reaction doesn't add a timeline item. - timeline.handle_live_redaction(&BOB, reaction_event_id).await; + timeline.handle_live_event(f.redaction(reaction_event_id).sender(&BOB)).await; let item = assert_next_matches!(stream, VectorDiff::Set { index: 0, value } => value); assert_eq!(item.reactions().len(), 0); assert_eq!(timeline.inner.items().await.len(), 2); @@ -190,13 +196,10 @@ async fn test_reaction_redaction_timeline_filter() { async fn test_receive_unredacted() { let timeline = TestTimeline::new(); + let f = EventFactory::new(); + // send two events, second one redacted - timeline - .handle_live_message_event( - &ALICE, - RoomMessageEventContent::text_plain("about to be redacted"), - ) - .await; + timeline.handle_live_event(f.text_msg("about to be redacted").sender(&ALICE)).await; timeline .handle_live_redacted_message_event(&ALICE, RedactedRoomMessageEventContent::new()) .await; @@ -205,7 +208,7 @@ async fn test_receive_unredacted() { let items = timeline.inner.items().await; assert!(items[0].is_day_divider()); let fst = items[1].as_event().unwrap(); - timeline.handle_live_redaction(&ALICE, fst.event_id().unwrap()).await; + timeline.handle_live_event(f.redaction(fst.event_id().unwrap()).sender(&ALICE)).await; let items = timeline.inner.items().await; assert_eq!(items.len(), 3); @@ -218,28 +221,21 @@ async fn test_receive_unredacted() { // send new events with the same event ID as the previous ones timeline - .handle_live_event(sync_timeline_event!({ - "content": { - "body": "unredacted #1", - "msgtype": "m.text", - }, - "sender": &*ALICE, - "event_id": fst.event_id().unwrap(), - "origin_server_ts": fst.timestamp(), - "type": "m.room.message", - })) + .handle_live_event( + f.text_msg("unredacted #1") + .sender(*ALICE) + .event_id(fst.event_id().unwrap()) + .server_ts(fst.timestamp()), + ) .await; + timeline - .handle_live_event(sync_timeline_event!({ - "content": { - "body": "unredacted #2", - "msgtype": "m.text", - }, - "sender": &*ALICE, - "event_id": snd.event_id().unwrap(), - "origin_server_ts": snd.timestamp(), - "type": "m.room.message", - })) + .handle_live_event( + f.text_msg("unredacted #2") + .sender(*ALICE) + .event_id(snd.event_id().unwrap()) + .server_ts(snd.timestamp()), + ) .await; // make sure we still have two redacted events diff --git a/crates/matrix-sdk/src/test_utils/events.rs b/crates/matrix-sdk/src/test_utils/events.rs index 699ed089e..bfb5cecd5 100644 --- a/crates/matrix-sdk/src/test_utils/events.rs +++ b/crates/matrix-sdk/src/test_utils/events.rs @@ -20,8 +20,12 @@ use matrix_sdk_base::deserialized_responses::{SyncTimelineEvent, TimelineEvent}; use matrix_sdk_test::{sync_timeline_event, timeline_event}; use ruma::{ events::{ - relation::InReplyTo, - room::message::{Relation, RoomMessageEventContent}, + reaction::ReactionEventContent, + relation::{Annotation, InReplyTo}, + room::{ + message::{Relation, RoomMessageEventContent}, + redaction::RoomRedactionEventContent, + }, AnySyncTimelineEvent, AnyTimelineEvent, EventContent, }, serde::Raw, @@ -35,6 +39,7 @@ pub struct EventBuilder { sender: Option, room: Option, event_id: Option, + redacts: Option, content: E, server_ts: MilliSecondsSinceUnixEpoch, } @@ -58,6 +63,11 @@ where self } + pub fn server_ts(mut self, ts: MilliSecondsSinceUnixEpoch) -> Self { + self.server_ts = ts; + self + } + pub fn into_raw_timeline(self) -> Raw { let room_id = self.room.expect("we should have a room id at this point"); let event_id = @@ -69,7 +79,8 @@ where "event_id": event_id, "sender": self.sender.expect("we should have a sender user id at this point"), "room_id": room_id, - "origin_server_ts": self.server_ts + "origin_server_ts": self.server_ts, + "redacts": self.redacts, }) } @@ -88,7 +99,8 @@ where "content": self.content, "event_id": event_id, "sender": self.sender.expect("we should have a sender user id at this point"), - "origin_server_ts": self.server_ts + "origin_server_ts": self.server_ts, + "redacts": self.redacts, }) } @@ -114,6 +126,15 @@ where } } +impl From> for SyncTimelineEvent +where + E::EventType: Serialize, +{ + fn from(val: EventBuilder) -> Self { + val.into_sync() + } +} + #[derive(Debug, Default)] pub struct EventFactory { next_ts: AtomicU64, @@ -145,12 +166,14 @@ impl EventFactory { ) } + /// Create an event from any event content. pub fn event(&self, content: E) -> EventBuilder { EventBuilder { sender: self.sender.clone(), room: self.room.clone(), server_ts: self.next_server_ts(), event_id: None, + redacts: None, content, } } @@ -165,6 +188,22 @@ impl EventFactory { self.event(RoomMessageEventContent::notice_plain(content)) } + /// Add a reaction to an event. + pub fn reaction( + &self, + event_id: &EventId, + annotation: String, + ) -> EventBuilder { + self.event(ReactionEventContent::new(Annotation::new(event_id.to_owned(), annotation))) + } + + /// Create a redaction for the given event id. + pub fn redaction(&self, event_id: &EventId) -> EventBuilder { + let mut builder = self.event(RoomRedactionEventContent::new_v11(event_id.to_owned())); + builder.redacts = Some(event_id.to_owned()); + builder + } + /// Set the next server timestamp. /// /// Timestamps will continue to increase by 1 (millisecond) from that value. diff --git a/testing/matrix-sdk-test/src/event_builder.rs b/testing/matrix-sdk-test/src/event_builder.rs index 5c9b480fb..f51836b7c 100644 --- a/testing/matrix-sdk-test/src/event_builder.rs +++ b/testing/matrix-sdk-test/src/event_builder.rs @@ -235,21 +235,6 @@ impl EventBuilder { ev_content } - pub fn make_redaction_event( - &self, - sender: &UserId, - redacts: &EventId, - ) -> Raw { - sync_timeline_event!({ - "type": "m.room.redaction", - "content": {}, - "redacts": redacts, - "event_id": EventId::new(server_name!("dummy.server")), - "sender": sender, - "origin_server_ts": self.next_server_ts(), - }) - } - pub fn make_reaction_event( &self, sender: &UserId,