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 {
41 let homeserver = homeserver.unwrap_or("http://localhost");
42
43 let default_builder = Client::builder()
44 .homeserver_url(homeserver)
45 .request_config(RequestConfig::new().disable_retry());
46
47 Self {
48 builder: default_builder,
49 auth_state: AuthState::LoggedInWithMatrixAuth {
50 token: None,
51 user_id: None,
52 device_id: None,
53 },
54 server_versions: ServerVersions::Default,
55 }
56 }
57
58 pub fn no_server_versions(mut self) -> Self {
60 self.server_versions = ServerVersions::None;
61 self
62 }
63
64 pub fn server_versions(mut self, versions: Vec<MatrixVersion>) -> Self {
66 self.server_versions = ServerVersions::Custom(versions);
67 self
68 }
69
70 pub fn unlogged(mut self) -> Self {
74 self.auth_state = AuthState::None;
75 self
76 }
77
78 pub fn registered_with_oauth(mut self) -> Self {
80 self.auth_state = AuthState::RegisteredWithOAuth;
81 self
82 }
83
84 pub fn logged_in_with_oauth(mut self) -> Self {
86 self.auth_state = AuthState::LoggedInWithOAuth;
87 self
88 }
89
90 pub fn logged_in_with_token(
92 mut self,
93 token: String,
94 user_id: OwnedUserId,
95 device_id: OwnedDeviceId,
96 ) -> Self {
97 self.auth_state = AuthState::LoggedInWithMatrixAuth {
98 token: Some(token),
99 user_id: Some(user_id),
100 device_id: Some(device_id),
101 };
102 self
103 }
104
105 pub fn on_builder<F: FnOnce(ClientBuilder) -> ClientBuilder>(mut self, f: F) -> Self {
124 self.builder = f(self.builder);
125 self
126 }
127
128 pub async fn build(self) -> Client {
130 let mut builder = self.builder;
131
132 if let Some(versions) = self.server_versions.into_vec() {
133 builder = builder.server_versions(versions);
134 }
135
136 let client = builder.build().await.expect("building client failed");
137
138 self.auth_state.maybe_restore_client(&client).await;
139
140 client
141 }
142}
143
144enum AuthState {
147 None,
149 LoggedInWithMatrixAuth {
151 token: Option<String>,
152 user_id: Option<OwnedUserId>,
153 device_id: Option<OwnedDeviceId>,
154 },
155 RegisteredWithOAuth,
157 LoggedInWithOAuth,
159}
160
161impl AuthState {
162 async fn maybe_restore_client(self, client: &Client) {
165 match self {
166 AuthState::None => {}
167 AuthState::LoggedInWithMatrixAuth { token, user_id, device_id } => {
168 client
169 .matrix_auth()
170 .restore_session(
171 MatrixSession {
172 meta: SessionMeta {
173 user_id: user_id.unwrap_or(owned_user_id!("@example:localhost")),
174 device_id: device_id.unwrap_or(owned_device_id!("DEVICEID")),
175 },
176 tokens: SessionTokens {
177 access_token: token.unwrap_or("1234".to_owned()).to_owned(),
178 refresh_token: None,
179 },
180 },
181 RoomLoadSettings::default(),
182 )
183 .await
184 .unwrap();
185 }
186 AuthState::RegisteredWithOAuth => {
187 client.oauth().restore_registered_client(oauth::mock_client_id());
188 }
189 AuthState::LoggedInWithOAuth => {
190 client
191 .oauth()
192 .restore_session(
193 oauth::mock_session(mock_session_tokens_with_refresh()),
194 RoomLoadSettings::default(),
195 )
196 .await
197 .unwrap();
198 }
199 }
200 }
201}
202
203enum ServerVersions {
205 Default,
207 None,
209 Custom(Vec<MatrixVersion>),
211}
212
213impl ServerVersions {
214 fn into_vec(self) -> Option<Vec<MatrixVersion>> {
218 match self {
219 Self::Default => Some(vec![MatrixVersion::V1_12]),
220 Self::None => None,
221 Self::Custom(versions) => Some(versions),
222 }
223 }
224}
225
226pub fn mock_session_meta() -> SessionMeta {
228 SessionMeta {
229 user_id: owned_user_id!("@example:localhost"),
230 device_id: owned_device_id!("DEVICEID"),
231 }
232}
233
234pub fn mock_session_tokens() -> SessionTokens {
237 SessionTokens { access_token: "1234".to_owned(), refresh_token: None }
238}
239
240pub fn mock_session_tokens_with_refresh() -> SessionTokens {
243 SessionTokens { access_token: "1234".to_owned(), refresh_token: Some("ZYXWV".to_owned()) }
244}
245
246pub fn mock_prev_session_tokens_with_refresh() -> SessionTokens {
249 SessionTokens {
250 access_token: "prev-access-token".to_owned(),
251 refresh_token: Some("prev-refresh-token".to_owned()),
252 }
253}
254
255pub fn mock_matrix_session() -> MatrixSession {
257 MatrixSession { meta: mock_session_meta(), tokens: mock_session_tokens() }
258}
259
260pub mod oauth {
262 use ruma::serde::Raw;
263 use url::Url;
264
265 use crate::{
266 SessionTokens,
267 authentication::oauth::{
268 ClientId, OAuthSession, UserSession,
269 registration::{ApplicationType, ClientMetadata, Localized, OAuthGrantType},
270 },
271 };
272
273 pub fn mock_client_id() -> ClientId {
275 ClientId::new("test_client_id".to_owned())
276 }
277
278 pub fn mock_redirect_uri() -> Url {
280 Url::parse("http://127.0.0.1/").expect("redirect URI should be valid")
281 }
282
283 pub fn mock_client_metadata() -> Raw<ClientMetadata> {
286 let client_uri = Url::parse("https://github.com/matrix-org/matrix-rust-sdk")
287 .expect("client URI should be valid");
288
289 let mut metadata = ClientMetadata::new(
290 ApplicationType::Native,
291 vec![
292 OAuthGrantType::AuthorizationCode { redirect_uris: vec![mock_redirect_uri()] },
293 OAuthGrantType::DeviceCode,
294 ],
295 Localized::new(client_uri, None),
296 );
297 metadata.client_name = Some(Localized::new("matrix-rust-sdk-test".to_owned(), None));
298
299 Raw::new(&metadata).expect("client metadata should serialize successfully")
300 }
301
302 pub fn mock_session(tokens: SessionTokens) -> OAuthSession {
304 OAuthSession {
305 client_id: mock_client_id(),
306 user: UserSession { meta: super::mock_session_meta(), tokens },
307 }
308 }
309}