matrix_sdk/test_utils/
mod.rs1#![allow(dead_code)]
4
5use assert_matches2::assert_let;
6use matrix_sdk_base::{deserialized_responses::TimelineEvent, store::RoomLoadSettings};
7use ruma::{
8 api::MatrixVersion,
9 events::{AnySyncMessageLikeEvent, AnySyncTimelineEvent, room::message::MessageType},
10};
11use url::Url;
12
13pub mod client;
14#[cfg(not(target_family = "wasm"))]
15pub mod mocks;
16
17use self::client::mock_matrix_session;
18use crate::{Client, ClientBuilder, config::RequestConfig};
19
20#[track_caller]
22pub fn assert_event_matches_msg<E: Clone + Into<TimelineEvent>>(event: &E, expected: &str) {
23 let event: TimelineEvent = event.clone().into();
24 let event = event.raw().deserialize().unwrap();
25 assert_let!(
26 AnySyncTimelineEvent::MessageLike(AnySyncMessageLikeEvent::RoomMessage(message)) = event
27 );
28 let message = message.as_original().unwrap();
29 assert_let!(MessageType::Text(text) = &message.content.msgtype);
30 assert_eq!(text.body, expected);
31}
32
33pub fn test_client_builder(homeserver_url: Option<String>) -> ClientBuilder {
36 let homeserver = homeserver_url
37 .map(|url| Url::try_from(url.as_str()).unwrap())
38 .unwrap_or_else(|| Url::try_from("http://localhost:1234").unwrap());
39 Client::builder().homeserver_url(homeserver).server_versions([MatrixVersion::V1_0])
40}
41
42pub async fn no_retry_test_client(homeserver_url: Option<String>) -> Client {
45 test_client_builder(homeserver_url)
46 .request_config(RequestConfig::new().disable_retry())
47 .build()
48 .await
49 .unwrap()
50}
51
52pub async fn set_client_session(client: &Client) {
54 client
55 .matrix_auth()
56 .restore_session(mock_matrix_session(), RoomLoadSettings::default())
57 .await
58 .unwrap();
59}
60
61pub async fn logged_in_client(homeserver_url: Option<String>) -> Client {
65 let client = no_retry_test_client(homeserver_url).await;
66 set_client_session(&client).await;
67 client
68}
69
70#[cfg(not(target_family = "wasm"))]
72pub async fn test_client_builder_with_server() -> (ClientBuilder, wiremock::MockServer) {
73 let server = wiremock::MockServer::start().await;
74 let builder = test_client_builder(Some(server.uri()));
75 (builder, server)
76}
77
78#[cfg(not(target_family = "wasm"))]
80pub async fn no_retry_test_client_with_server() -> (Client, wiremock::MockServer) {
81 let server = wiremock::MockServer::start().await;
82 let client = no_retry_test_client(Some(server.uri().to_string())).await;
83 (client, server)
84}
85
86#[cfg(not(target_family = "wasm"))]
88pub async fn logged_in_client_with_server() -> (Client, wiremock::MockServer) {
89 let server = wiremock::MockServer::start().await;
90 let client = logged_in_client(Some(server.uri().to_string())).await;
91 (client, server)
92}
93
94#[macro_export]
122macro_rules! assert_next_with_timeout {
123 ($stream:expr) => {
124 $crate::assert_next_with_timeout!($stream, 500)
125 };
126 ($stream:expr, $timeout_ms:expr) => {{
127 #[allow(unused_imports)]
129 use futures_util::StreamExt as _;
130 tokio::time::timeout(std::time::Duration::from_millis($timeout_ms), $stream.next())
131 .await
132 .expect("Next event timed out")
133 .expect("No next event received")
134 }};
135}
136
137#[macro_export]
140macro_rules! assert_recv_with_timeout {
141 ($receiver:expr, $timeout_ms:expr) => {{
142 tokio::time::timeout(std::time::Duration::from_millis($timeout_ms), $receiver.recv())
143 .await
144 .expect("Next event timed out")
145 .expect("No next event received")
146 }};
147}
148
149#[macro_export]
154macro_rules! assert_next_matches_with_timeout {
155 ($stream:expr, $pat:pat) => {
156 $crate::assert_next_matches_with_timeout!($stream, $pat => {})
157 };
158 ($stream:expr, $pat:pat => $arm:expr) => {
159 $crate::assert_next_matches_with_timeout!($stream, 100, $pat => $arm)
160 };
161 ($stream:expr, $timeout_ms:expr, $pat:pat) => {
162 $crate::assert_next_matches_with_timeout!($stream, $timeout_ms, $pat => {})
163 };
164 ($stream:expr, $timeout_ms:expr, $pat:pat => $arm:expr) => {
165 match $crate::assert_next_with_timeout!(&mut $stream, $timeout_ms) {
166 $pat => $arm,
167 val => {
168 ::core::panic!(
169 "assertion failed: `{:?}` does not match `{}`",
170 val, ::core::stringify!($pat)
171 );
172 }
173 }
174 };
175}
176
177#[macro_export]
213macro_rules! assert_next_eq_with_timeout {
214 ($stream:expr, $expected:expr) => {
215 $crate::assert_next_eq_with_timeout_impl!($stream, $expected, std::time::Duration::from_millis(100));
216 };
217 ($stream:expr, $expected:expr, $timeout:literal ms) => {
218 $crate::assert_next_eq_with_timeout_impl!($stream, $expected, std::time::Duration::from_millis($timeout));
219 };
220 ($stream:expr, $expected:expr, $timeout:literal ms, $($msg:tt)*) => {
221 $crate::assert_next_eq_with_timeout_impl!($stream, $expected, std::time::Duration::from_millis($timeout), $($msg)*);
222 };
223 ($stream:expr, $expected:expr, $($msg:tt)*) => {
224 $crate::assert_next_eq_with_timeout_impl!($stream, $expected, std::time::Duration::from_millis(100), $($msg)*);
225 };
226}
227
228#[macro_export]
253macro_rules! assert_decrypted_message_eq {
254 ($event:expr, $expected:expr, $($msg:tt)*) => {{
255 assert_matches2::assert_let!($crate::deserialized_responses::TimelineEventKind::Decrypted(decrypted_event) = $event.kind);
256
257 let deserialized_event = decrypted_event
258 .event
259 .deserialize()
260 .expect("We should be able to deserialize the decrypted event");
261
262 assert_matches2::assert_let!(
263 $crate::ruma::events::AnyTimelineEvent::MessageLike(deserialized_event) = deserialized_event
264 );
265
266 let content =
267 deserialized_event.original_content().expect("The event should not have been redacted");
268 assert_matches2::assert_let!($crate::ruma::events::AnyMessageLikeEventContent::RoomMessage(content) = content);
269 assert_eq!(content.body(), $expected, $($msg)*);
270 }};
271 ($event:expr, $expected:expr) => {{
272 assert_decrypted_message_eq!($event, $expected, "The decrypted content did not match to the expected value");
273 }};
274}
275
276#[macro_export]
305macro_rules! assert_let_decrypted_state_event_content {
306 ($pat:pat = $event:expr, $($msg:tt)*) => {
307 assert_matches2::assert_let!(
308 $crate::deserialized_responses::TimelineEventKind::Decrypted(decrypted_event) =
309 $event.kind,
310 "Event was not decrypted"
311 );
312
313 let deserialized_event = decrypted_event
314 .event
315 .deserialize_as_unchecked::<$crate::ruma::events::AnyStateEvent>()
316 .expect("We should be able to deserialize the decrypted event");
317
318 let content =
319 deserialized_event.original_content().expect("The event should not have been redacted");
320
321 assert_matches2::assert_let!($pat = content, $($msg)*);
322 };
323 ($pat:pat = $event:expr) => {
324 assert_let_decrypted_state_event_content!(
325 $pat = $event,
326 "The decrypted event did not match the expected value"
327 );
328 };
329}
330
331#[doc(hidden)]
332#[macro_export]
333macro_rules! assert_next_eq_with_timeout_impl {
334 ($stream:expr, $expected:expr, $timeout:expr) => {
335 let next_value = tokio::time::timeout(
336 $timeout,
337 $stream.next()
338 )
339 .await
340 .expect("We should be able to get the next value out of the stream by now")
341 .expect("The stream should have given us a new value instead of None");
342
343 assert_eq!(next_value, $expected);
344 };
345 ($stream:expr, $expected:expr, $timeout:expr, $($msg:tt)*) => {{
346 let next_value = tokio::time::timeout(
347 $timeout,
348 futures_util::StreamExt::next(&mut $stream)
349 )
350 .await
351 .expect("We should be able to get the next value out of the stream by now")
352 .expect("The stream should have given us a new value instead of None");
353
354 assert_eq!(next_value, $expected, $($msg)*);
355 }};
356}
357
358#[macro_export]
362macro_rules! assert_let_timeout {
363 ($timeout:expr, $pat:pat = $future:expr) => {
364 assert_matches2::assert_let!(Ok($pat) = tokio::time::timeout($timeout, $future).await);
365 };
366
367 ($pat:pat = $future:expr) => {
368 assert_let_timeout!(std::time::Duration::from_millis(100), $pat = $future);
369 };
370}