matrix_sdk/test_utils/
client.rs1use matrix_sdk_base::{SessionMeta, store::RoomLoadSettings};
18use ruma::{OwnedDeviceId, OwnedUserId, api::MatrixVersion, owned_device_id, owned_user_id};
19
20use crate::{
21 Client, ClientBuilder, SessionTokens, authentication::matrix::MatrixSession,
22 config::RequestConfig,
23};
24
25#[allow(missing_debug_implementations)]
27pub struct MockClientBuilder {
28 builder: ClientBuilder,
29 auth_state: AuthState,
30 server_versions: ServerVersions,
31}
32
33impl MockClientBuilder {
34 pub fn new(homeserver: Option<&str>) -> Self {
40 let homeserver = homeserver.unwrap_or("http://localhost");
41
42 let default_builder = Client::builder()
43 .homeserver_url(homeserver)
44 .request_config(RequestConfig::new().disable_retry());
45
46 Self {
47 builder: default_builder,
48 auth_state: AuthState::LoggedInWithMatrixAuth {
49 token: None,
50 user_id: None,
51 device_id: None,
52 },
53 server_versions: ServerVersions::Default,
54 }
55 }
56
57 pub fn no_server_versions(mut self) -> Self {
59 self.server_versions = ServerVersions::None;
60 self
61 }
62
63 pub fn server_versions(mut self, versions: Vec<MatrixVersion>) -> Self {
65 self.server_versions = ServerVersions::Custom(versions);
66 self
67 }
68
69 pub fn unlogged(mut self) -> Self {
73 self.auth_state = AuthState::None;
74 self
75 }
76
77 pub fn registered_with_oauth(mut self) -> Self {
79 self.auth_state = AuthState::RegisteredWithOAuth;
80 self
81 }
82
83 pub fn logged_in_with_oauth(mut self) -> Self {
85 self.auth_state = AuthState::LoggedInWithOAuth;
86 self
87 }
88
89 pub fn logged_in_with_token(
91 mut self,
92 token: String,
93 user_id: OwnedUserId,
94 device_id: OwnedDeviceId,
95 ) -> Self {
96 self.auth_state = AuthState::LoggedInWithMatrixAuth {
97 token: Some(token),
98 user_id: Some(user_id),
99 device_id: Some(device_id),
100 };
101 self
102 }
103
104 pub fn on_builder<F: FnOnce(ClientBuilder) -> ClientBuilder>(mut self, f: F) -> Self {
123 self.builder = f(self.builder);
124 self
125 }
126
127 pub async fn build(self) -> Client {
129 let mut builder = self.builder;
130
131 if let Some(versions) = self.server_versions.into_vec() {
132 builder = builder.server_versions(versions);
133 }
134
135 let client = builder.build().await.expect("building client failed");
136
137 self.auth_state.maybe_restore_client(&client).await;
138
139 client
140 }
141}
142
143enum AuthState {
146 None,
148 LoggedInWithMatrixAuth {
150 token: Option<String>,
151 user_id: Option<OwnedUserId>,
152 device_id: Option<OwnedDeviceId>,
153 },
154 RegisteredWithOAuth,
156 LoggedInWithOAuth,
158}
159
160impl AuthState {
161 async fn maybe_restore_client(self, client: &Client) {
164 match self {
165 AuthState::None => {}
166 AuthState::LoggedInWithMatrixAuth { token, user_id, device_id } => {
167 client
168 .matrix_auth()
169 .restore_session(
170 MatrixSession {
171 meta: SessionMeta {
172 user_id: user_id.unwrap_or(owned_user_id!("@example:localhost")),
173 device_id: device_id.unwrap_or(owned_device_id!("DEVICEID")),
174 },
175 tokens: SessionTokens {
176 access_token: token.unwrap_or("1234".to_owned()).to_owned(),
177 refresh_token: None,
178 },
179 },
180 RoomLoadSettings::default(),
181 )
182 .await
183 .unwrap();
184 }
185 AuthState::RegisteredWithOAuth => {
186 client.oauth().restore_registered_client(oauth::mock_client_id());
187 }
188 AuthState::LoggedInWithOAuth => {
189 client
190 .oauth()
191 .restore_session(
192 oauth::mock_session(mock_session_tokens_with_refresh()),
193 RoomLoadSettings::default(),
194 )
195 .await
196 .unwrap();
197 }
198 }
199 }
200}
201
202enum ServerVersions {
204 Default,
206 None,
208 Custom(Vec<MatrixVersion>),
210}
211
212impl ServerVersions {
213 fn into_vec(self) -> Option<Vec<MatrixVersion>> {
217 match self {
218 Self::Default => Some(vec![MatrixVersion::V1_12]),
219 Self::None => None,
220 Self::Custom(versions) => Some(versions),
221 }
222 }
223}
224
225pub fn mock_session_meta() -> SessionMeta {
227 SessionMeta {
228 user_id: owned_user_id!("@example:localhost"),
229 device_id: owned_device_id!("DEVICEID"),
230 }
231}
232
233pub fn mock_session_tokens() -> SessionTokens {
236 SessionTokens { access_token: "1234".to_owned(), refresh_token: None }
237}
238
239pub fn mock_session_tokens_with_refresh() -> SessionTokens {
242 SessionTokens { access_token: "1234".to_owned(), refresh_token: Some("ZYXWV".to_owned()) }
243}
244
245pub fn mock_prev_session_tokens_with_refresh() -> SessionTokens {
248 SessionTokens {
249 access_token: "prev-access-token".to_owned(),
250 refresh_token: Some("prev-refresh-token".to_owned()),
251 }
252}
253
254pub fn mock_matrix_session() -> MatrixSession {
256 MatrixSession { meta: mock_session_meta(), tokens: mock_session_tokens() }
257}
258
259pub mod oauth {
261 use ruma::serde::Raw;
262 use url::Url;
263
264 use crate::{
265 SessionTokens,
266 authentication::oauth::{
267 ClientId, OAuthSession, UserSession,
268 registration::{ApplicationType, ClientMetadata, Localized, OAuthGrantType},
269 },
270 };
271
272 pub fn mock_client_id() -> ClientId {
274 ClientId::new("test_client_id".to_owned())
275 }
276
277 pub fn mock_redirect_uri() -> Url {
279 Url::parse("http://127.0.0.1/").expect("redirect URI should be valid")
280 }
281
282 pub fn mock_client_metadata() -> Raw<ClientMetadata> {
285 let client_uri = Url::parse("https://github.com/matrix-org/matrix-rust-sdk")
286 .expect("client URI should be valid");
287
288 let mut metadata = ClientMetadata::new(
289 ApplicationType::Native,
290 vec![
291 OAuthGrantType::AuthorizationCode { redirect_uris: vec![mock_redirect_uri()] },
292 OAuthGrantType::DeviceCode,
293 ],
294 Localized::new(client_uri, None),
295 );
296 metadata.client_name = Some(Localized::new("matrix-rust-sdk-test".to_owned(), None));
297
298 Raw::new(&metadata).expect("client metadata should serialize successfully")
299 }
300
301 pub fn mock_session(tokens: SessionTokens) -> OAuthSession {
303 OAuthSession {
304 client_id: mock_client_id(),
305 user: UserSession { meta: super::mock_session_meta(), tokens },
306 }
307 }
308}