diff --git a/crates/matrix-sdk-ui/src/timeline/event_item/mod.rs b/crates/matrix-sdk-ui/src/timeline/event_item/mod.rs
index 475f5e23f..aa0ecbc54 100644
--- a/crates/matrix-sdk-ui/src/timeline/event_item/mod.rs
+++ b/crates/matrix-sdk-ui/src/timeline/event_item/mod.rs
@@ -716,23 +716,24 @@ impl ReactionsByKeyBySender {
mod tests {
use assert_matches::assert_matches;
use assert_matches2::assert_let;
- use matrix_sdk::test_utils::logged_in_client;
+ use matrix_sdk::test_utils::{events::EventFactory, logged_in_client};
use matrix_sdk_base::{
deserialized_responses::SyncTimelineEvent, latest_event::LatestEvent, sliding_sync::http,
MinimalStateEvent, OriginalMinimalStateEvent,
};
use matrix_sdk_test::{async_test, sync_timeline_event};
use ruma::{
+ event_id,
events::{
room::{
member::RoomMemberEventContent,
message::{MessageFormat, MessageType},
},
- AnySyncTimelineEvent,
+ AnySyncTimelineEvent, BundledMessageLikeRelations,
},
room_id,
serde::Raw,
- user_id, RoomId, UInt, UserId,
+ uint, user_id, MilliSecondsSinceUnixEpoch, RoomId, UInt, UserId,
};
use super::{EventTimelineItem, Profile};
@@ -773,48 +774,30 @@ mod tests {
// contains a bundled edit,
let room_id = room_id!("!q:x.uk");
let user_id = user_id!("@t:o.uk");
- let event = sync_timeline_event!({
- "event_id": "$eventid6",
- "sender": user_id,
- "origin_server_ts": 42,
- "type": "m.room.message",
- "room_id": room_id,
- "content": {
- "body": "**My M**",
- "format": "org.matrix.custom.html",
- "formatted_body": "My M" ,
- "msgtype": "m.text"
- },
- "unsigned": {
- "m.relations": {
- "m.replace" : {
- "sender" : user_id,
- "content" : {
- "format" : "org.matrix.custom.html",
- "formatted_body" : " * Updated!",
- "m.relates_to" : {
- "event_id" : "$eventid6",
- "rel_type" : "m.replace"
- },
- "m.new_content": {
- "body" : "Updated!",
- "formatted_body" : "Updated!",
- "msgtype" : "m.text",
- "format" : "org.matrix.custom.html"
- },
- "msgtype" : "m.text",
- "body" : " * Updated!"
- },
- "origin_server_ts" : 43,
- "room_id" : room_id,
- "event_id" : "$edit-event-id",
- "user_id" : user_id,
- "type" : "m.room.message",
- }
- }
- }
- })
- .into();
+
+ let f = EventFactory::new();
+
+ let original_event_id = event_id!("$original");
+
+ let mut relations = BundledMessageLikeRelations::new();
+ relations.replace = Some(Box::new(
+ f.text_html(" * Updated!", " * Updated!")
+ .edit(
+ original_event_id,
+ MessageType::text_html("Updated!", "Updated!").into(),
+ )
+ .event_id(event_id!("$edit"))
+ .sender(user_id)
+ .into_raw_sync(),
+ ));
+
+ let event = f
+ .text_html("**My M**", "My M")
+ .sender(user_id)
+ .event_id(original_event_id)
+ .bundled_relations(relations)
+ .server_ts(MilliSecondsSinceUnixEpoch(uint!(42)))
+ .into_sync();
let client = logged_in_client(None).await;
diff --git a/crates/matrix-sdk-ui/src/timeline/tests/edit.rs b/crates/matrix-sdk-ui/src/timeline/tests/edit.rs
index 33fa44f02..ddfcdead8 100644
--- a/crates/matrix-sdk-ui/src/timeline/tests/edit.rs
+++ b/crates/matrix-sdk-ui/src/timeline/tests/edit.rs
@@ -19,11 +19,13 @@ use eyeball_im::VectorDiff;
use matrix_sdk::deserialized_responses::{
AlgorithmInfo, EncryptionInfo, VerificationLevel, VerificationState,
};
-use matrix_sdk_test::{async_test, sync_timeline_event, ALICE};
+use matrix_sdk_test::{async_test, ALICE};
use ruma::{
event_id,
- events::room::message::{MessageType, RedactedRoomMessageEventContent},
- server_name, EventId,
+ events::{
+ room::message::{MessageType, RedactedRoomMessageEventContent},
+ BundledMessageLikeRelations,
+ },
};
use stream_assert::{assert_next_matches, assert_pending};
@@ -108,45 +110,36 @@ async fn test_aggregated_sanitized() {
let timeline = TestTimeline::new();
let mut stream = timeline.subscribe().await;
- let original_event_id = EventId::new(server_name!("dummy.server"));
- let ev = sync_timeline_event!({
- "content": {
- "formatted_body": "original message",
- "format": "org.matrix.custom.html",
- "body": "**original** message",
- "msgtype": "m.text"
- },
- "event_id": &original_event_id,
- "origin_server_ts": timeline.event_builder.next_server_ts(),
- "sender": *ALICE,
- "type": "m.room.message",
- "unsigned": {
- "m.relations": {
- "m.replace": {
- "content": {
- "formatted_body": "* better message",
- "format": "org.matrix.custom.html",
- "body": "* !!edited!! **better** message",
- "m.new_content": {
- "formatted_body": " better message",
- "format": "org.matrix.custom.html",
- "body": "!!edited!! **better** message",
- "msgtype": "m.text"
- },
- "m.relates_to": {
- "event_id": original_event_id,
- "rel_type": "m.replace"
- },
- "msgtype": "m.text"
- },
- "event_id": EventId::new(server_name!("dummy.server")),
- "origin_server_ts": timeline.event_builder.next_server_ts(),
- "sender": *ALICE,
- "type": "m.room.message",
- }
- }
- }
- });
+ let original_event_id = event_id!("$original");
+ let edit_event_id = event_id!("$edit");
+
+ let f = &timeline.factory;
+
+ let mut relations = BundledMessageLikeRelations::new();
+ relations.replace = Some(Box::new(
+ f.text_html(
+ "* !!edited!! **better** message",
+ "* better message",
+ )
+ .edit(
+ original_event_id,
+ MessageType::text_html(
+ "!!edited!! **better** message",
+ " better message",
+ )
+ .into(),
+ )
+ .event_id(edit_event_id)
+ .sender(*ALICE)
+ .into_raw_sync(),
+ ));
+
+ let ev = f
+ .text_html("**original** message", "original message")
+ .sender(*ALICE)
+ .event_id(original_event_id)
+ .bundled_relations(relations);
+
timeline.handle_live_event(ev).await;
let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value);
@@ -246,38 +239,21 @@ async fn test_relations_edit_overrides_pending_edit() {
assert_pending!(stream);
// Now we receive the original event, with a bundled relations group.
- let ev = sync_timeline_event!({
- "content": {
- "body": "original",
- "msgtype": "m.text"
- },
- "event_id": &original_event_id,
- "origin_server_ts": timeline.event_builder.next_server_ts(),
- "sender": *ALICE,
- "type": "m.room.message",
- "unsigned": {
- "m.relations": {
- "m.replace": {
- "content": {
- "body": "* edit 2",
- "m.new_content": {
- "body": "edit 2",
- "msgtype": "m.text"
- },
- "m.relates_to": {
- "event_id": original_event_id,
- "rel_type": "m.replace"
- },
- "msgtype": "m.text"
- },
- "event_id": edit2_event_id,
- "origin_server_ts": timeline.event_builder.next_server_ts(),
- "sender": *ALICE,
- "type": "m.room.message",
- }
- }
- }
- });
+ let mut relations = BundledMessageLikeRelations::new();
+ relations.replace = Some(Box::new(
+ f.text_msg("* edit 2")
+ .edit(original_event_id, MessageType::text_plain("edit 2").into())
+ .event_id(edit2_event_id)
+ .sender(*ALICE)
+ .into_raw_sync(),
+ ));
+
+ let ev = f
+ .text_msg("original")
+ .sender(*ALICE)
+ .event_id(original_event_id)
+ .bundled_relations(relations);
+
timeline.handle_live_event(ev).await;
let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value);
diff --git a/crates/matrix-sdk/src/test_utils/events.rs b/crates/matrix-sdk/src/test_utils/events.rs
index ce7b0bb5f..260e210b4 100644
--- a/crates/matrix-sdk/src/test_utils/events.rs
+++ b/crates/matrix-sdk/src/test_utils/events.rs
@@ -34,7 +34,7 @@ use ruma::{
message::{Relation, RoomMessageEventContent, RoomMessageEventContentWithoutRelation},
redaction::RoomRedactionEventContent,
},
- AnySyncTimelineEvent, AnyTimelineEvent, EventContent,
+ AnySyncTimelineEvent, AnyTimelineEvent, BundledMessageLikeRelations, EventContent,
},
serde::Raw,
server_name, EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedRoomId,
@@ -43,18 +43,19 @@ use ruma::{
use serde::Serialize;
use serde_json::json;
-#[derive(Debug, Default, Serialize)]
+#[derive(Debug, Default)]
struct Unsigned {
transaction_id: Option,
+ relations: Option>>,
}
#[derive(Debug)]
-pub struct EventBuilder {
+pub struct EventBuilder {
sender: Option,
room: Option,
event_id: Option,
redacts: Option,
- content: E,
+ content: C,
server_ts: MilliSecondsSinceUnixEpoch,
unsigned: Option,
state_key: Option,
@@ -90,6 +91,21 @@ where
self
}
+ /// Adds bundled relations to this event.
+ ///
+ /// Ideally, we'd type-check that an event passed as a relation is the same
+ /// type as this one, but it's not trivial to do so because this builder
+ /// is only generic on the event's *content*, not the event type itself;
+ /// doing so would require many changes, and this is testing code after
+ /// all.
+ pub fn bundled_relations(
+ mut self,
+ relations: BundledMessageLikeRelations>,
+ ) -> Self {
+ self.unsigned.get_or_insert_with(Default::default).relations = Some(relations);
+ self
+ }
+
pub fn state_key(mut self, state_key: impl Into) -> Self {
self.state_key = Some(state_key.into());
self
@@ -122,9 +138,23 @@ where
if let Some(redacts) = self.redacts {
map.insert("redacts".to_owned(), json!(redacts));
}
+
if let Some(unsigned) = self.unsigned {
- map.insert("unsigned".to_owned(), json!(unsigned));
+ let mut unsigned_json = json!({});
+
+ // We can't plain serialize `Unsigned`, otherwise this would result in some
+ // `null` fields when options are set to none, which Ruma rejects.
+ let unsigned_obj = unsigned_json.as_object_mut().unwrap();
+ if let Some(transaction_id) = unsigned.transaction_id {
+ unsigned_obj.insert("transaction_id".to_owned(), json!(transaction_id));
+ }
+ if let Some(relations) = unsigned.relations {
+ unsigned_obj.insert("m.relations".to_owned(), json!(relations));
+ }
+
+ map.insert("unsigned".to_owned(), unsigned_json);
}
+
if let Some(state_key) = self.state_key {
map.insert("state_key".to_owned(), json!(state_key));
}