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::{room::message::MessageType, AnySyncMessageLikeEvent, AnySyncTimelineEvent},
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::{config::RequestConfig, Client, ClientBuilder};
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 => $arm:expr) => {
162 match $crate::assert_next_with_timeout!(&mut $stream, $timeout_ms) {
163 $pat => $arm,
164 val => {
165 ::core::panic!(
166 "assertion failed: `{:?}` does not match `{}`",
167 val, ::core::stringify!($pat)
168 );
169 }
170 }
171 };
172}
173
174#[macro_export]
210macro_rules! assert_next_eq_with_timeout {
211 ($stream:expr, $expected:expr) => {
212 $crate::assert_next_eq_with_timeout_impl!($stream, $expected, std::time::Duration::from_millis(100));
213 };
214 ($stream:expr, $expected:expr, $timeout:literal ms) => {
215 $crate::assert_next_eq_with_timeout_impl!($stream, $expected, std::time::Duration::from_millis($timeout));
216 };
217 ($stream:expr, $expected:expr, $timeout:literal ms, $($msg:tt)*) => {
218 $crate::assert_next_eq_with_timeout_impl!($stream, $expected, std::time::Duration::from_millis($timeout), $($msg)*);
219 };
220 ($stream:expr, $expected:expr, $($msg:tt)*) => {
221 $crate::assert_next_eq_with_timeout_impl!($stream, $expected, std::time::Duration::from_millis(100), $($msg)*);
222 };
223}
224
225#[macro_export]
250macro_rules! assert_decrypted_message_eq {
251 ($event:expr, $expected:expr, $($msg:tt)*) => {{
252 assert_matches2::assert_let!($crate::deserialized_responses::TimelineEventKind::Decrypted(decrypted_event) = $event.kind);
253
254 let deserialized_event = decrypted_event
255 .event
256 .deserialize()
257 .expect("We should be able to deserialize the decrypted event");
258
259 assert_matches2::assert_let!(
260 $crate::ruma::events::AnyTimelineEvent::MessageLike(deserialized_event) = deserialized_event
261 );
262
263 let content =
264 deserialized_event.original_content().expect("The event should not have been redacted");
265 assert_matches2::assert_let!($crate::ruma::events::AnyMessageLikeEventContent::RoomMessage(content) = content);
266 assert_eq!(content.body(), $expected, $($msg)*);
267 }};
268 ($event:expr, $expected:expr) => {{
269 assert_decrypted_message_eq!($event, $expected, "The decrypted content did not match to the expected value");
270 }};
271}
272
273#[macro_export]
302macro_rules! assert_let_decrypted_state_event_content {
303 ($pat:pat = $event:expr, $($msg:tt)*) => {
304 assert_matches2::assert_let!(
305 $crate::deserialized_responses::TimelineEventKind::Decrypted(decrypted_event) =
306 $event.kind,
307 "Event was not decrypted"
308 );
309
310 let deserialized_event = decrypted_event
311 .event
312 .deserialize_as_unchecked::<$crate::ruma::events::AnyStateEvent>()
313 .expect("We should be able to deserialize the decrypted event");
314
315 let content =
316 deserialized_event.original_content().expect("The event should not have been redacted");
317
318 assert_matches2::assert_let!($pat = content, $($msg)*);
319 };
320 ($pat:pat = $event:expr) => {
321 assert_let_decrypted_state_event_content!(
322 $pat = $event,
323 "The decrypted event did not match the expected value"
324 );
325 };
326}
327
328#[doc(hidden)]
329#[macro_export]
330macro_rules! assert_next_eq_with_timeout_impl {
331 ($stream:expr, $expected:expr, $timeout:expr) => {
332 let next_value = tokio::time::timeout(
333 $timeout,
334 $stream.next()
335 )
336 .await
337 .expect("We should be able to get the next value out of the stream by now")
338 .expect("The stream should have given us a new value instead of None");
339
340 assert_eq!(next_value, $expected);
341 };
342 ($stream:expr, $expected:expr, $timeout:expr, $($msg:tt)*) => {{
343 let next_value = tokio::time::timeout(
344 $timeout,
345 futures_util::StreamExt::next(&mut $stream)
346 )
347 .await
348 .expect("We should be able to get the next value out of the stream by now")
349 .expect("The stream should have given us a new value instead of None");
350
351 assert_eq!(next_value, $expected, $($msg)*);
352 }};
353}
354
355#[macro_export]
359macro_rules! assert_let_timeout {
360 ($timeout:expr, $pat:pat = $future:expr) => {
361 assert_matches2::assert_let!(Ok($pat) = tokio::time::timeout($timeout, $future).await);
362 };
363
364 ($pat:pat = $future:expr) => {
365 assert_let_timeout!(std::time::Duration::from_millis(100), $pat = $future);
366 };
367}