mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-05-18 13:40:55 -04:00
testing: Add sync_timeline_event macro for more type safety in tests
This commit is contained in:
committed by
Jonas Platte
parent
82f793ec0f
commit
c8a4bc799b
@@ -15,7 +15,8 @@
|
||||
use assert_matches::assert_matches;
|
||||
use eyeball_im::VectorDiff;
|
||||
use imbl::vector;
|
||||
use matrix_sdk_test::async_test;
|
||||
use matrix_sdk_base::deserialized_responses::SyncTimelineEvent;
|
||||
use matrix_sdk_test::{async_test, sync_timeline_event};
|
||||
use ruma::{
|
||||
assign,
|
||||
events::{
|
||||
@@ -29,10 +30,9 @@ use ruma::{
|
||||
FullStateEventContent,
|
||||
},
|
||||
};
|
||||
use serde_json::json;
|
||||
use stream_assert::assert_next_matches;
|
||||
|
||||
use super::{sync_timeline_event, TestTimeline, ALICE, BOB};
|
||||
use super::{TestTimeline, ALICE, BOB};
|
||||
use crate::timeline::{
|
||||
event_item::AnyOtherFullStateEventContent, tests::CAROL, MembershipChange, TimelineDetails,
|
||||
TimelineItemContent, TimelineItemKind, VirtualTimelineItem,
|
||||
@@ -46,10 +46,10 @@ async fn initial_events() {
|
||||
timeline
|
||||
.inner
|
||||
.add_initial_events(vector![
|
||||
sync_timeline_event(
|
||||
SyncTimelineEvent::new(
|
||||
timeline.make_message_event(*ALICE, RoomMessageEventContent::text_plain("A")),
|
||||
),
|
||||
sync_timeline_event(
|
||||
SyncTimelineEvent::new(
|
||||
timeline.make_message_event(*BOB, RoomMessageEventContent::text_plain("B")),
|
||||
),
|
||||
])
|
||||
@@ -69,7 +69,7 @@ async fn sticker() {
|
||||
let mut stream = timeline.subscribe_events().await;
|
||||
|
||||
timeline
|
||||
.handle_live_custom_event(json!({
|
||||
.handle_live_custom_event(sync_timeline_event!({
|
||||
"content": {
|
||||
"body": "Happy sticker",
|
||||
"info": {
|
||||
@@ -195,7 +195,11 @@ async fn dedup_pagination() {
|
||||
|
||||
let event = timeline.make_message_event(*ALICE, RoomMessageEventContent::text_plain("o/"));
|
||||
timeline.handle_live_custom_event(event.clone()).await;
|
||||
timeline.handle_back_paginated_custom_event(event).await;
|
||||
// This cast is not actually correct, sync events aren't valid
|
||||
// back-paginated events, as they are missing `room_id`. However, the
|
||||
// timeline doesn't care about that `room_id` and casts back to
|
||||
// `Raw<AnySyncTimelineEvent>` before attempting to deserialize.
|
||||
timeline.handle_back_paginated_custom_event(event.cast()).await;
|
||||
|
||||
let timeline_items = timeline.inner.items().await;
|
||||
assert_eq!(timeline_items.len(), 2);
|
||||
@@ -210,13 +214,13 @@ async fn dedup_pagination() {
|
||||
async fn dedup_initial() {
|
||||
let mut timeline = TestTimeline::new();
|
||||
|
||||
let event_a = sync_timeline_event(
|
||||
let event_a = SyncTimelineEvent::new(
|
||||
timeline.make_message_event(*ALICE, RoomMessageEventContent::text_plain("A")),
|
||||
);
|
||||
let event_b = sync_timeline_event(
|
||||
let event_b = SyncTimelineEvent::new(
|
||||
timeline.make_message_event(*BOB, RoomMessageEventContent::text_plain("B")),
|
||||
);
|
||||
let event_c = sync_timeline_event(
|
||||
let event_c = SyncTimelineEvent::new(
|
||||
timeline.make_message_event(*CAROL, RoomMessageEventContent::text_plain("C")),
|
||||
);
|
||||
|
||||
|
||||
@@ -17,12 +17,11 @@ use std::{io, sync::Arc};
|
||||
use assert_matches::assert_matches;
|
||||
use eyeball_im::VectorDiff;
|
||||
use matrix_sdk::Error;
|
||||
use matrix_sdk_test::async_test;
|
||||
use matrix_sdk_test::{async_test, sync_timeline_event};
|
||||
use ruma::{
|
||||
event_id,
|
||||
events::{room::message::RoomMessageEventContent, AnyMessageLikeEventContent},
|
||||
};
|
||||
use serde_json::json;
|
||||
use stream_assert::assert_next_matches;
|
||||
|
||||
use super::{TestTimeline, ALICE, BOB};
|
||||
@@ -94,7 +93,7 @@ async fn remote_echo_full_trip() {
|
||||
// Now, a sync has been run against the server, and an event with the same ID
|
||||
// comes in.
|
||||
timeline
|
||||
.handle_live_custom_event(json!({
|
||||
.handle_live_custom_event(sync_timeline_event!({
|
||||
"content": {
|
||||
"body": "echo",
|
||||
"msgtype": "m.text",
|
||||
@@ -140,7 +139,7 @@ async fn remote_echo_new_position() {
|
||||
|
||||
// When the remote echo comes in…
|
||||
timeline
|
||||
.handle_live_custom_event(json!({
|
||||
.handle_live_custom_event(sync_timeline_event!({
|
||||
"content": {
|
||||
"body": "echo",
|
||||
"msgtype": "m.text",
|
||||
@@ -190,7 +189,7 @@ async fn day_divider_duplication() {
|
||||
// … when the second remote event is re-received (day still the same)
|
||||
let event_id = items[2].as_event().unwrap().event_id().unwrap();
|
||||
timeline
|
||||
.handle_live_custom_event(json!({
|
||||
.handle_live_custom_event(sync_timeline_event!({
|
||||
"content": {
|
||||
"body": "B",
|
||||
"msgtype": "m.text",
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
use assert_matches::assert_matches;
|
||||
use eyeball_im::VectorDiff;
|
||||
use matrix_sdk_test::async_test;
|
||||
use matrix_sdk_test::{async_test, sync_timeline_event};
|
||||
use ruma::{
|
||||
assign,
|
||||
events::{
|
||||
@@ -23,10 +23,8 @@ use ruma::{
|
||||
self, MessageType, RedactedRoomMessageEventContent, RoomMessageEventContent,
|
||||
},
|
||||
},
|
||||
serde::Raw,
|
||||
server_name, EventId,
|
||||
};
|
||||
use serde_json::json;
|
||||
use stream_assert::assert_next_matches;
|
||||
|
||||
use super::{TestTimeline, ALICE};
|
||||
@@ -112,7 +110,7 @@ async fn aggregated_sanitized() {
|
||||
let mut stream = timeline.subscribe().await;
|
||||
|
||||
let original_event_id = EventId::new(server_name!("dummy.server"));
|
||||
let ev = json!({
|
||||
let ev = sync_timeline_event!({
|
||||
"content": {
|
||||
"formatted_body": "<strong>original</strong> message",
|
||||
"format": "org.matrix.custom.html",
|
||||
@@ -150,7 +148,7 @@ async fn aggregated_sanitized() {
|
||||
}
|
||||
}
|
||||
});
|
||||
timeline.handle_live_event(Raw::new(&ev).unwrap().cast()).await;
|
||||
timeline.handle_live_event(ev).await;
|
||||
|
||||
let _day_divider = assert_next_matches!(stream, VectorDiff::PushBack { value } => value);
|
||||
let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value);
|
||||
|
||||
@@ -16,7 +16,7 @@ use std::sync::Arc;
|
||||
|
||||
use assert_matches::assert_matches;
|
||||
use eyeball_im::VectorDiff;
|
||||
use matrix_sdk_test::async_test;
|
||||
use matrix_sdk_test::{async_test, sync_timeline_event};
|
||||
use ruma::{
|
||||
assign,
|
||||
events::{
|
||||
@@ -32,7 +32,6 @@ use ruma::{
|
||||
AnySyncTimelineEvent,
|
||||
},
|
||||
};
|
||||
use serde_json::json;
|
||||
use stream_assert::assert_next_matches;
|
||||
|
||||
use super::{TestTimeline, ALICE, BOB};
|
||||
@@ -176,7 +175,7 @@ async fn hide_failed_to_parse() {
|
||||
// m.room.message events must have a msgtype and body in content, so this
|
||||
// event with an empty content object should fail to deserialize.
|
||||
timeline
|
||||
.handle_live_custom_event(json!({
|
||||
.handle_live_custom_event(sync_timeline_event!({
|
||||
"content": {},
|
||||
"event_id": "$eeG0HA0FAZ37wP8kXlNkxx3I",
|
||||
"origin_server_ts": 10,
|
||||
@@ -188,7 +187,7 @@ async fn hide_failed_to_parse() {
|
||||
// Similar to above, the m.room.member state event must also not have an
|
||||
// empty content object.
|
||||
timeline
|
||||
.handle_live_custom_event(json!({
|
||||
.handle_live_custom_event(sync_timeline_event!({
|
||||
"content": {},
|
||||
"event_id": "$d5G0HA0FAZ37wP8kXlNkxx3I",
|
||||
"origin_server_ts": 2179,
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
use assert_matches::assert_matches;
|
||||
use eyeball_im::VectorDiff;
|
||||
use matrix_sdk_test::async_test;
|
||||
use matrix_sdk_test::{async_test, sync_timeline_event};
|
||||
use ruma::{
|
||||
assign,
|
||||
events::{
|
||||
@@ -24,7 +24,6 @@ use ruma::{
|
||||
},
|
||||
uint, MilliSecondsSinceUnixEpoch,
|
||||
};
|
||||
use serde_json::json;
|
||||
use stream_assert::assert_next_matches;
|
||||
|
||||
use super::{TestTimeline, ALICE, BOB};
|
||||
@@ -64,7 +63,7 @@ async fn invalid_event_content() {
|
||||
// m.room.message events must have a msgtype and body in content, so this
|
||||
// event with an empty content object should fail to deserialize.
|
||||
timeline
|
||||
.handle_live_custom_event(json!({
|
||||
.handle_live_custom_event(sync_timeline_event!({
|
||||
"content": {},
|
||||
"event_id": "$eeG0HA0FAZ37wP8kXlNkxx3I",
|
||||
"origin_server_ts": 10,
|
||||
@@ -86,7 +85,7 @@ async fn invalid_event_content() {
|
||||
// Similar to above, the m.room.member state event must also not have an
|
||||
// empty content object.
|
||||
timeline
|
||||
.handle_live_custom_event(json!({
|
||||
.handle_live_custom_event(sync_timeline_event!({
|
||||
"content": {},
|
||||
"event_id": "$d5G0HA0FAZ37wP8kXlNkxx3I",
|
||||
"origin_server_ts": 2179,
|
||||
@@ -119,7 +118,7 @@ async fn invalid_event() {
|
||||
// This event is missing the sender field which the homeserver must add to
|
||||
// all timeline events. Because the event is malformed, it will be ignored.
|
||||
timeline
|
||||
.handle_live_custom_event(json!({
|
||||
.handle_live_custom_event(sync_timeline_event!({
|
||||
"content": {
|
||||
"body": "hello world",
|
||||
"msgtype": "m.text"
|
||||
|
||||
@@ -29,15 +29,16 @@ use futures_core::Stream;
|
||||
use futures_util::{FutureExt, StreamExt};
|
||||
use indexmap::IndexMap;
|
||||
use matrix_sdk::deserialized_responses::{SyncTimelineEvent, TimelineEvent};
|
||||
use matrix_sdk_test::sync_timeline_event;
|
||||
use once_cell::sync::Lazy;
|
||||
use ruma::{
|
||||
events::{
|
||||
receipt::{Receipt, ReceiptEventContent, ReceiptThread, ReceiptType},
|
||||
relation::Annotation,
|
||||
room::redaction::RoomRedactionEventContent,
|
||||
AnyMessageLikeEventContent, AnySyncTimelineEvent, EmptyStateKey, MessageLikeEventContent,
|
||||
RedactedMessageLikeEventContent, RedactedStateEventContent, StateEventContent,
|
||||
StaticStateEventContent,
|
||||
AnyMessageLikeEventContent, AnySyncTimelineEvent, AnyTimelineEvent, EmptyStateKey,
|
||||
MessageLikeEventContent, RedactedMessageLikeEventContent, RedactedStateEventContent,
|
||||
StateEventContent, StaticStateEventContent,
|
||||
},
|
||||
int,
|
||||
power_levels::NotificationPowerLevels,
|
||||
@@ -75,11 +76,6 @@ static ALICE: Lazy<&UserId> = Lazy::new(|| user_id!("@alice:server.name"));
|
||||
static BOB: Lazy<&UserId> = Lazy::new(|| user_id!("@bob:other.server"));
|
||||
static CAROL: Lazy<&UserId> = Lazy::new(|| user_id!("@carol:other.server"));
|
||||
|
||||
fn sync_timeline_event(event: JsonValue) -> SyncTimelineEvent {
|
||||
let event = serde_json::from_value(event).unwrap();
|
||||
SyncTimelineEvent { event, encryption_info: None, push_actions: Vec::default() }
|
||||
}
|
||||
|
||||
struct TestTimeline {
|
||||
inner: TimelineInner<TestRoomDataProvider>,
|
||||
next_ts: AtomicU64,
|
||||
@@ -133,7 +129,7 @@ impl TestTimeline {
|
||||
C: StaticStateEventContent<StateKey = EmptyStateKey>,
|
||||
{
|
||||
let ev = self.make_state_event(sender, "", content, prev_content);
|
||||
self.handle_live_event(Raw::new(&ev).unwrap().cast()).await;
|
||||
self.handle_live_event(ev).await;
|
||||
}
|
||||
|
||||
async fn handle_live_state_event_with_state_key<C>(
|
||||
@@ -169,13 +165,12 @@ impl TestTimeline {
|
||||
self.handle_live_event(Raw::new(&ev).unwrap().cast()).await;
|
||||
}
|
||||
|
||||
async fn handle_live_custom_event(&self, event: JsonValue) {
|
||||
let raw = Raw::new(&event).unwrap().cast();
|
||||
self.handle_live_event(raw).await;
|
||||
async fn handle_live_custom_event(&self, event: Raw<AnySyncTimelineEvent>) {
|
||||
self.handle_live_event(event).await;
|
||||
}
|
||||
|
||||
async fn handle_live_redaction(&self, sender: &UserId, redacts: &EventId) {
|
||||
let ev = json!({
|
||||
let ev = sync_timeline_event!({
|
||||
"type": "m.room.redaction",
|
||||
"content": {},
|
||||
"redacts": redacts,
|
||||
@@ -183,13 +178,12 @@ impl TestTimeline {
|
||||
"sender": sender,
|
||||
"origin_server_ts": self.next_server_ts(),
|
||||
});
|
||||
let raw = Raw::new(&ev).unwrap().cast();
|
||||
self.handle_live_event(raw).await;
|
||||
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 = json!({
|
||||
let ev = sync_timeline_event!({
|
||||
"type": "m.reaction",
|
||||
"content": {
|
||||
"m.relates_to": {
|
||||
@@ -202,8 +196,7 @@ impl TestTimeline {
|
||||
"sender": sender,
|
||||
"origin_server_ts": self.next_server_ts(),
|
||||
});
|
||||
let raw = Raw::new(&ev).unwrap().cast();
|
||||
self.handle_live_event(raw).await;
|
||||
self.handle_live_event(ev).await;
|
||||
event_id
|
||||
}
|
||||
|
||||
@@ -228,8 +221,8 @@ impl TestTimeline {
|
||||
txn_id
|
||||
}
|
||||
|
||||
async fn handle_back_paginated_custom_event(&self, event: JsonValue) {
|
||||
let timeline_event = TimelineEvent::new(Raw::new(&event).unwrap().cast());
|
||||
async fn handle_back_paginated_custom_event(&self, event: Raw<AnyTimelineEvent>) {
|
||||
let timeline_event = TimelineEvent::new(event.cast());
|
||||
self.inner.handle_back_paginated_events(vec![timeline_event]).await;
|
||||
}
|
||||
|
||||
@@ -267,7 +260,7 @@ impl TestTimeline {
|
||||
&self,
|
||||
sender: &UserId,
|
||||
content: C,
|
||||
) -> JsonValue {
|
||||
) -> Raw<AnySyncTimelineEvent> {
|
||||
self.make_message_event_with_id(sender, content, EventId::new(server_name!("dummy.server")))
|
||||
}
|
||||
|
||||
@@ -276,8 +269,8 @@ impl TestTimeline {
|
||||
sender: &UserId,
|
||||
content: C,
|
||||
event_id: OwnedEventId,
|
||||
) -> JsonValue {
|
||||
json!({
|
||||
) -> Raw<AnySyncTimelineEvent> {
|
||||
sync_timeline_event!({
|
||||
"type": content.event_type(),
|
||||
"content": content,
|
||||
"event_id": event_id,
|
||||
@@ -290,8 +283,8 @@ impl TestTimeline {
|
||||
&self,
|
||||
sender: &UserId,
|
||||
content: C,
|
||||
) -> JsonValue {
|
||||
json!({
|
||||
) -> Raw<AnySyncTimelineEvent> {
|
||||
sync_timeline_event!({
|
||||
"type": content.event_type(),
|
||||
"content": content,
|
||||
"event_id": EventId::new(server_name!("dummy.server")),
|
||||
@@ -307,14 +300,14 @@ impl TestTimeline {
|
||||
state_key: &str,
|
||||
content: C,
|
||||
prev_content: Option<C>,
|
||||
) -> JsonValue {
|
||||
) -> Raw<AnySyncTimelineEvent> {
|
||||
let unsigned = if let Some(prev_content) = prev_content {
|
||||
json!({ "prev_content": prev_content })
|
||||
} else {
|
||||
json!({})
|
||||
};
|
||||
|
||||
json!({
|
||||
sync_timeline_event!({
|
||||
"type": content.event_type(),
|
||||
"state_key": state_key,
|
||||
"content": content,
|
||||
@@ -330,8 +323,8 @@ impl TestTimeline {
|
||||
sender: &UserId,
|
||||
state_key: &str,
|
||||
content: C,
|
||||
) -> JsonValue {
|
||||
json!({
|
||||
) -> Raw<AnySyncTimelineEvent> {
|
||||
sync_timeline_event!({
|
||||
"type": content.event_type(),
|
||||
"state_key": state_key,
|
||||
"content": content,
|
||||
@@ -359,8 +352,8 @@ impl TestTimeline {
|
||||
sender: &UserId,
|
||||
annotation: &Annotation,
|
||||
timestamp: MilliSecondsSinceUnixEpoch,
|
||||
) -> JsonValue {
|
||||
json!({
|
||||
) -> Raw<AnySyncTimelineEvent> {
|
||||
sync_timeline_event!({
|
||||
"event_id": EventId::new(server_name!("dummy.server")),
|
||||
"content": {
|
||||
"m.relates_to": {
|
||||
|
||||
@@ -11,7 +11,6 @@ use ruma::{
|
||||
},
|
||||
AnyMessageLikeEventContent,
|
||||
},
|
||||
serde::Raw,
|
||||
server_name, EventId, OwnedEventId, UserId,
|
||||
};
|
||||
|
||||
@@ -217,8 +216,7 @@ impl TestTimeline {
|
||||
NewUnstablePollStartEventContent::new(content).into(),
|
||||
);
|
||||
let event = self.make_message_event_with_id(sender, event_content, event_id.to_owned());
|
||||
let raw = Raw::new(&event).unwrap().cast();
|
||||
self.handle_live_event(raw).await;
|
||||
self.handle_live_event(event).await;
|
||||
}
|
||||
|
||||
async fn send_poll_response(&self, sender: &UserId, answers: Vec<&str>, poll_id: &EventId) {
|
||||
|
||||
@@ -18,6 +18,7 @@ use assert_matches::assert_matches;
|
||||
use eyeball_im::VectorDiff;
|
||||
use futures_core::Stream;
|
||||
use imbl::vector;
|
||||
use matrix_sdk_base::deserialized_responses::SyncTimelineEvent;
|
||||
use matrix_sdk_test::async_test;
|
||||
use ruma::{
|
||||
events::{relation::Annotation, room::message::RoomMessageEventContent},
|
||||
@@ -29,10 +30,7 @@ use crate::timeline::{
|
||||
event_item::EventItemIdentifier,
|
||||
inner::ReactionAction,
|
||||
reactions::ReactionToggleResult,
|
||||
tests::{
|
||||
assert_event_is_updated, assert_no_more_updates, sync_timeline_event, TestTimeline, ALICE,
|
||||
BOB,
|
||||
},
|
||||
tests::{assert_event_is_updated, assert_no_more_updates, TestTimeline, ALICE, BOB},
|
||||
TimelineItem,
|
||||
};
|
||||
|
||||
@@ -249,12 +247,12 @@ async fn initial_reaction_timestamp_is_stored() {
|
||||
timeline
|
||||
.inner
|
||||
.add_initial_events(vector![
|
||||
sync_timeline_event(timeline.make_reaction(
|
||||
SyncTimelineEvent::new(timeline.make_reaction(
|
||||
*ALICE,
|
||||
&Annotation::new(message_event_id.clone(), REACTION_KEY.to_owned()),
|
||||
reaction_timestamp
|
||||
)),
|
||||
sync_timeline_event(timeline.make_message_event_with_id(
|
||||
SyncTimelineEvent::new(timeline.make_message_event_with_id(
|
||||
*ALICE,
|
||||
RoomMessageEventContent::text_plain("A"),
|
||||
message_event_id
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
use assert_matches::assert_matches;
|
||||
use eyeball_im::VectorDiff;
|
||||
use imbl::vector;
|
||||
use matrix_sdk_test::async_test;
|
||||
use matrix_sdk_base::deserialized_responses::SyncTimelineEvent;
|
||||
use matrix_sdk_test::{async_test, sync_timeline_event};
|
||||
use ruma::{
|
||||
events::{
|
||||
reaction::{ReactionEventContent, RedactedReactionEventContent},
|
||||
@@ -31,10 +32,9 @@ use ruma::{
|
||||
},
|
||||
owned_room_id,
|
||||
};
|
||||
use serde_json::json;
|
||||
use stream_assert::assert_next_matches;
|
||||
|
||||
use super::{sync_timeline_event, TestTimeline, ALICE, BOB};
|
||||
use super::{TestTimeline, ALICE, BOB};
|
||||
use crate::timeline::{AnyOtherFullStateEventContent, TimelineDetails, TimelineItemContent};
|
||||
|
||||
#[async_test]
|
||||
@@ -146,7 +146,7 @@ async fn reaction_redaction_timeline_filter() {
|
||||
// Initialise a timeline with a redacted reaction.
|
||||
timeline
|
||||
.inner
|
||||
.add_initial_events(vector![sync_timeline_event(
|
||||
.add_initial_events(vector![SyncTimelineEvent::new(
|
||||
timeline.make_redacted_message_event(*ALICE, RedactedReactionEventContent::new())
|
||||
)])
|
||||
.await;
|
||||
@@ -209,7 +209,7 @@ async fn receive_unredacted() {
|
||||
|
||||
// send new events with the same event ID as the previous ones
|
||||
timeline
|
||||
.handle_live_custom_event(json!({
|
||||
.handle_live_custom_event(sync_timeline_event!({
|
||||
"content": {
|
||||
"body": "unredacted #1",
|
||||
"msgtype": "m.text",
|
||||
@@ -221,7 +221,7 @@ async fn receive_unredacted() {
|
||||
}))
|
||||
.await;
|
||||
timeline
|
||||
.handle_live_custom_event(json!({
|
||||
.handle_live_custom_event(sync_timeline_event!({
|
||||
"content": {
|
||||
"body": "unredacted #2",
|
||||
"msgtype": "m.text",
|
||||
|
||||
@@ -3,6 +3,18 @@ pub use matrix_sdk_test_macros::async_test;
|
||||
use ruma::api::{client::sync::sync_events::v3::Response as SyncResponse, IncomingResponse};
|
||||
use serde_json::Value as JsonValue;
|
||||
|
||||
/// Create a `Raw<AnySyncTimelineEvent>` from arbitrary JSON.
|
||||
///
|
||||
/// Forwards all arguments to [`serde_json::json`].
|
||||
#[macro_export]
|
||||
macro_rules! sync_timeline_event {
|
||||
($( $tt:tt )*) => {
|
||||
::ruma::serde::Raw::new(&::serde_json::json!( $($tt)* ))
|
||||
.unwrap()
|
||||
.cast::<::ruma::events::AnySyncTimelineEvent>()
|
||||
}
|
||||
}
|
||||
|
||||
pub mod notification_settings;
|
||||
mod sync_builder;
|
||||
pub mod test_json;
|
||||
|
||||
Reference in New Issue
Block a user