test(sdk): Move the integration tests

This moves the bulk of the Client tests into integration tests.
This commit is contained in:
Damir Jelić
2022-07-08 12:08:27 +02:00
committed by GitHub
8 changed files with 2076 additions and 2021 deletions

View File

@@ -175,7 +175,7 @@ jobs:
steps:
- name: Checkout the repo
uses: actions/checkout@v2
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
@@ -184,24 +184,24 @@ jobs:
components: clippy
profile: minimal
override: true
- name: Install wasm-pack
uses: jetli/wasm-pack-action@v0.3.0
with:
version: latest
- name: Load cache
uses: Swatinem/rust-cache@v1
- name: Install nextest
uses: taiki-e/install-action@nextest
- name: Rust Check
uses: actions-rs/cargo@v1
with:
command: run
args: -p xtask -- ci wasm ${{ matrix.cmd }}
- name: Wasm-Pack test
uses: actions-rs/cargo@v1
with:

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,591 @@
// mockito (the http mocking library) is not supported for wasm32
#![cfg(not(target_arch = "wasm32"))]
use std::{collections::BTreeMap, str::FromStr, time::Duration};
use matrix_sdk::{
config::SyncSettings,
media::{MediaFormat, MediaRequest, MediaThumbnailSize},
Error, HttpError, RumaApiError,
};
use matrix_sdk_test::{async_test, test_json};
use mockito::{mock, Matcher};
use ruma::{
api::{
client::{
self as client_api,
account::register::{v3::Request as RegistrationRequest, RegistrationKind},
directory::{
get_public_rooms,
get_public_rooms_filtered::{self, v3::Request as PublicRoomsFilterRequest},
},
media::get_content_thumbnail::v3::Method,
session::get_login_types::v3::LoginType,
uiaa::{self, UiaaResponse},
},
error::{FromHttpResponseError, ServerError},
},
assign, device_id,
directory::Filter,
events::room::{message::ImageMessageEventContent, ImageInfo, MediaSource},
mxc_uri, room_id, uint, user_id,
};
use serde_json::json;
use url::Url;
use crate::{logged_in_client, no_retry_test_client};
#[async_test]
async fn set_homeserver() {
let client = no_retry_test_client().await;
let homeserver = Url::from_str("http://example.com/").unwrap();
client.set_homeserver(homeserver.clone()).await;
assert_eq!(client.homeserver().await, homeserver);
}
#[async_test]
async fn login() {
let homeserver = Url::from_str(&mockito::server_url()).unwrap();
let client = no_retry_test_client().await;
let _m_types = mock("GET", "/_matrix/client/r0/login")
.with_status(200)
.with_body(test_json::LOGIN_TYPES.to_string())
.create();
let can_password = client
.get_login_types()
.await
.unwrap()
.flows
.iter()
.any(|flow| matches!(flow, LoginType::Password(_)));
assert!(can_password);
let _m_login = mock("POST", "/_matrix/client/r0/login")
.with_status(200)
.with_body(test_json::LOGIN.to_string())
.create();
client.login_username("example", "wordpass").send().await.unwrap();
let logged_in = client.logged_in();
assert!(logged_in, "Client should be logged in");
assert_eq!(client.homeserver().await, homeserver);
}
#[async_test]
async fn login_with_discovery() {
let client = no_retry_test_client().await;
let _m_login = mock("POST", "/_matrix/client/r0/login")
.with_status(200)
.with_body(test_json::LOGIN_WITH_DISCOVERY.to_string())
.create();
client.login_username("example", "wordpass").send().await.unwrap();
let logged_in = client.logged_in();
assert!(logged_in, "Client should be logged in");
assert_eq!(client.homeserver().await.as_str(), "https://example.org/");
}
#[async_test]
async fn login_no_discovery() {
let client = no_retry_test_client().await;
let _m_login = mock("POST", "/_matrix/client/r0/login")
.with_status(200)
.with_body(test_json::LOGIN.to_string())
.create();
client.login_username("example", "wordpass").send().await.unwrap();
let logged_in = client.logged_in();
assert!(logged_in, "Client should be logged in");
assert_eq!(client.homeserver().await, Url::parse(&mockito::server_url()).unwrap());
}
#[async_test]
#[cfg(feature = "sso-login")]
async fn login_with_sso() {
let _m_login = mock("POST", "/_matrix/client/r0/login")
.with_status(200)
.with_body(test_json::LOGIN.to_string())
.create();
let _homeserver = Url::from_str(&mockito::server_url()).unwrap();
let client = no_retry_test_client().await;
let idp = ruma::api::client::session::get_login_types::v3::IdentityProvider::new(
"some-id".to_owned(),
"idp-name".to_owned(),
);
client
.login_sso(|sso_url| async move {
let sso_url = Url::parse(&sso_url).unwrap();
let (_, redirect) =
sso_url.query_pairs().find(|(key, _)| key == "redirectUrl").unwrap();
let mut redirect_url = Url::parse(&redirect).unwrap();
redirect_url.set_query(Some("loginToken=tinytoken"));
reqwest::get(redirect_url.to_string()).await.unwrap();
Ok(())
})
.identity_provider_id(&idp.id)
.send()
.await
.unwrap();
let logged_in = client.logged_in();
assert!(logged_in, "Client should be logged in");
}
#[async_test]
async fn login_with_sso_token() {
let client = no_retry_test_client().await;
let _m = mock("GET", "/_matrix/client/r0/login")
.with_status(200)
.with_body(test_json::LOGIN_TYPES.to_string())
.create();
let can_sso = client
.get_login_types()
.await
.unwrap()
.flows
.iter()
.any(|flow| matches!(flow, LoginType::Sso(_)));
assert!(can_sso);
let sso_url = client.get_sso_login_url("http://127.0.0.1:3030", None).await;
assert!(sso_url.is_ok());
let _m = mock("POST", "/_matrix/client/r0/login")
.with_status(200)
.with_body(test_json::LOGIN.to_string())
.create();
client.login_token("averysmalltoken").send().await.unwrap();
let logged_in = client.logged_in();
assert!(logged_in, "Client should be logged in");
}
#[async_test]
async fn login_error() {
let client = no_retry_test_client().await;
let _m = mock("POST", "/_matrix/client/r0/login")
.with_status(403)
.with_body(test_json::LOGIN_RESPONSE_ERR.to_string())
.create();
if let Err(err) = client.login_username("example", "wordpass").send().await {
if let Error::Http(HttpError::Api(FromHttpResponseError::Server(ServerError::Known(
RumaApiError::ClientApi(client_api::Error { kind, message, status_code }),
)))) = err
{
if let client_api::error::ErrorKind::Forbidden = kind {
} else {
panic!("found the wrong `ErrorKind` {:?}, expected `Forbidden", kind);
}
assert_eq!(message, "Invalid password".to_owned());
assert_eq!(status_code, http::StatusCode::from_u16(403).unwrap());
} else {
panic!("found the wrong `Error` type {:?}, expected `Error::RumaResponse", err);
}
} else {
panic!("this request should return an `Err` variant")
}
}
#[async_test]
async fn register_error() {
let client = no_retry_test_client().await;
let _m = mock("POST", Matcher::Regex(r"^/_matrix/client/r0/register\?.*$".to_owned()))
.with_status(403)
.with_body(test_json::REGISTRATION_RESPONSE_ERR.to_string())
.create();
let user = assign!(RegistrationRequest::new(), {
username: Some("user"),
password: Some("password"),
auth: Some(uiaa::AuthData::FallbackAcknowledgement(
uiaa::FallbackAcknowledgement::new("foobar"),
)),
kind: RegistrationKind::User,
});
if let Err(err) = client.register(user).await {
if let HttpError::UiaaError(FromHttpResponseError::Server(ServerError::Known(
UiaaResponse::MatrixError(client_api::Error { kind, message, status_code }),
))) = err
{
if let client_api::error::ErrorKind::Forbidden = kind {
} else {
panic!("found the wrong `ErrorKind` {:?}, expected `Forbidden", kind);
}
assert_eq!(message, "Invalid password".to_owned());
assert_eq!(status_code, http::StatusCode::from_u16(403).unwrap());
} else {
panic!("found the wrong `Error` type {:#?}, expected `UiaaResponse`", err);
}
} else {
panic!("this request should return an `Err` variant")
}
}
#[async_test]
async fn sync() {
let client = logged_in_client().await;
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.with_body(test_json::SYNC.to_string())
.match_header("authorization", "Bearer 1234")
.create();
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
let response = client.sync_once(sync_settings).await.unwrap();
assert_ne!(response.next_batch, "");
assert!(client.sync_token().await.is_some());
}
#[async_test]
async fn devices() {
let client = logged_in_client().await;
let _m = mock("GET", "/_matrix/client/r0/devices")
.with_status(200)
.with_body(test_json::DEVICES.to_string())
.create();
assert!(client.devices().await.is_ok());
}
#[async_test]
async fn delete_devices() {
let client = no_retry_test_client().await;
let _m = mock("POST", "/_matrix/client/r0/delete_devices")
.with_status(401)
.with_body(
json!({
"flows": [
{
"stages": [
"m.login.password"
]
}
],
"params": {},
"session": "vBslorikviAjxzYBASOBGfPp"
})
.to_string(),
)
.create();
let _m = mock("POST", "/_matrix/client/r0/delete_devices")
.with_status(401)
// empty response
// TODO rename that response type.
.with_body(test_json::LOGOUT.to_string())
.create();
let devices = &[device_id!("DEVICEID").to_owned()];
if let Err(e) = client.delete_devices(devices, None).await {
if let Some(info) = e.uiaa_response() {
let mut auth_parameters = BTreeMap::new();
let identifier = json!({
"type": "m.id.user",
"user": "example",
});
auth_parameters.insert("identifier".to_owned(), identifier);
auth_parameters.insert("password".to_owned(), "wordpass".into());
let auth_data = uiaa::AuthData::Password(assign!(
uiaa::Password::new(
uiaa::UserIdentifier::UserIdOrLocalpart("example"),
"wordpass",
), {
session: info.session.as_deref(),
}
));
client.delete_devices(devices, Some(auth_data)).await.unwrap();
}
}
}
#[async_test]
async fn resolve_room_alias() {
let client = no_retry_test_client().await;
let _m = mock("GET", "/_matrix/client/r0/directory/room/%23alias%3Aexample%2Eorg")
.with_status(200)
.with_body(test_json::GET_ALIAS.to_string())
.create();
let alias = ruma::room_alias_id!("#alias:example.org");
assert!(client.resolve_room_alias(alias).await.is_ok());
}
#[async_test]
async fn join_leave_room() {
let room_id = room_id!("!SVkFJHzfwvuaIEawgC:localhost");
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.with_body(test_json::SYNC.to_string())
.create();
let client = logged_in_client().await;
let session = client.session().unwrap().clone();
let room = client.get_joined_room(room_id);
assert!(room.is_none());
client.sync_once(SyncSettings::default()).await.unwrap();
let room = client.get_left_room(room_id);
assert!(room.is_none());
let room = client.get_joined_room(room_id);
assert!(room.is_some());
// test store reloads with correct room state from the state store
let joined_client = no_retry_test_client().await;
joined_client.restore_login(session).await.unwrap();
// joined room reloaded from state store
joined_client.sync_once(SyncSettings::default()).await.unwrap();
let room = joined_client.get_joined_room(room_id);
assert!(room.is_some());
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.with_body(test_json::LEAVE_SYNC_EVENT.to_string())
.create();
joined_client.sync_once(SyncSettings::default()).await.unwrap();
let room = joined_client.get_joined_room(room_id);
assert!(room.is_none());
let room = joined_client.get_left_room(room_id);
assert!(room.is_some());
}
#[async_test]
async fn join_room_by_id() {
let client = logged_in_client().await;
let _m = mock("POST", Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/join".to_owned()))
.with_status(200)
.with_body(test_json::ROOM_ID.to_string())
.match_header("authorization", "Bearer 1234")
.create();
let room_id = room_id!("!testroom:example.org");
assert_eq!(
// this is the `join_by_room_id::Response` but since no PartialEq we check the RoomId
// field
client.join_room_by_id(room_id).await.unwrap().room_id,
room_id
);
}
#[async_test]
async fn join_room_by_id_or_alias() {
let client = logged_in_client().await;
let _m = mock("POST", Matcher::Regex(r"^/_matrix/client/r0/join/".to_owned()))
.with_status(200)
.with_body(test_json::ROOM_ID.to_string())
.match_header("authorization", "Bearer 1234")
.create();
let room_id = room_id!("!testroom:example.org").into();
assert_eq!(
// this is the `join_by_room_id::Response` but since no PartialEq we check the RoomId
// field
client
.join_room_by_id_or_alias(room_id, &["server.com".try_into().unwrap()])
.await
.unwrap()
.room_id,
room_id!("!testroom:example.org")
);
}
#[async_test]
async fn room_search_all() {
let client = no_retry_test_client().await;
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/publicRooms".to_owned()))
.with_status(200)
.with_body(test_json::PUBLIC_ROOMS.to_string())
.create();
let get_public_rooms::v3::Response { chunk, .. } =
client.public_rooms(Some(10), None, None).await.unwrap();
assert_eq!(chunk.len(), 1);
}
#[async_test]
async fn room_search_filtered() {
let client = logged_in_client().await;
let _m = mock("POST", Matcher::Regex(r"^/_matrix/client/r0/publicRooms".to_owned()))
.with_status(200)
.with_body(test_json::PUBLIC_ROOMS.to_string())
.match_header("authorization", "Bearer 1234")
.create();
let generic_search_term = Some("cheese");
let filter = assign!(Filter::new(), { generic_search_term });
let request = assign!(PublicRoomsFilterRequest::new(), { filter });
let get_public_rooms_filtered::v3::Response { chunk, .. } =
client.public_rooms_filtered(request).await.unwrap();
assert_eq!(chunk.len(), 1);
}
#[async_test]
async fn invited_rooms() {
let client = logged_in_client().await;
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::INVITE_SYNC.to_string())
.create();
let _response = client.sync_once(SyncSettings::default()).await.unwrap();
assert!(client.joined_rooms().is_empty());
assert!(client.left_rooms().is_empty());
assert!(!client.invited_rooms().is_empty());
assert!(client.get_invited_room(room_id!("!696r7674:example.com")).is_some());
}
#[async_test]
async fn left_rooms() {
let client = logged_in_client().await;
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::LEAVE_SYNC.to_string())
.create();
let _response = client.sync_once(SyncSettings::default()).await.unwrap();
assert!(client.joined_rooms().is_empty());
assert!(!client.left_rooms().is_empty());
assert!(client.invited_rooms().is_empty());
assert!(client.get_left_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).is_some())
}
#[async_test]
async fn get_media_content() {
let client = logged_in_client().await;
let request = MediaRequest {
source: MediaSource::Plain(mxc_uri!("mxc://localhost/textfile").to_owned()),
format: MediaFormat::File,
};
let m = mock(
"GET",
Matcher::Regex(r"^/_matrix/media/r0/download/localhost/textfile\?.*$".to_owned()),
)
.with_status(200)
.with_body("Some very interesting text.")
.expect(2)
.create();
assert!(client.get_media_content(&request, true).await.is_ok());
assert!(client.get_media_content(&request, true).await.is_ok());
assert!(client.get_media_content(&request, false).await.is_ok());
m.assert();
}
#[async_test]
async fn get_media_file() {
let client = logged_in_client().await;
let event_content = ImageMessageEventContent::plain(
"filename.jpg".into(),
mxc_uri!("mxc://example.org/image").to_owned(),
Some(Box::new(assign!(ImageInfo::new(), {
height: Some(uint!(398)),
width: Some(uint!(394)),
mimetype: Some("image/jpeg".into()),
size: Some(uint!(31037)),
}))),
);
let m = mock(
"GET",
Matcher::Regex(r"^/_matrix/media/r0/download/example%2Eorg/image\?.*$".to_owned()),
)
.with_status(200)
.with_body("binaryjpegdata")
.create();
assert!(client.get_file(event_content.clone(), true).await.is_ok());
assert!(client.get_file(event_content.clone(), true).await.is_ok());
m.assert();
let m = mock(
"GET",
Matcher::Regex(r"^/_matrix/media/r0/thumbnail/example%2Eorg/image\?.*$".to_owned()),
)
.with_status(200)
.with_body("smallerbinaryjpegdata")
.create();
assert!(client
.get_thumbnail(
event_content,
MediaThumbnailSize { method: Method::Scale, width: uint!(100), height: uint!(100) },
true
)
.await
.is_ok());
m.assert();
}
#[async_test]
async fn whoami() {
let client = logged_in_client().await;
let _m = mock("GET", "/_matrix/client/r0/account/whoami")
.with_status(200)
.with_body(test_json::WHOAMI.to_string())
.match_header("authorization", "Bearer 1234")
.create();
let user_id = user_id!("@joe:example.org");
assert_eq!(client.whoami().await.unwrap().user_id, user_id);
}

View File

@@ -0,0 +1,31 @@
use matrix_sdk::{config::RequestConfig, Client, ClientBuilder, Session};
use ruma::{api::MatrixVersion, device_id, user_id};
use url::Url;
mod client;
mod room;
fn test_client_builder() -> ClientBuilder {
let homeserver = Url::parse(&mockito::server_url()).unwrap();
Client::builder().homeserver_url(homeserver).server_versions([MatrixVersion::V1_0])
}
async fn no_retry_test_client() -> Client {
test_client_builder()
.request_config(RequestConfig::new().disable_retry())
.build()
.await
.unwrap()
}
async fn logged_in_client() -> Client {
let session = Session {
access_token: "1234".to_owned(),
user_id: user_id!("@example:localhost").to_owned(),
device_id: device_id!("DEVICEID").to_owned(),
};
let client = no_retry_test_client().await;
client.restore_login(session).await.unwrap();
client
}

View File

@@ -0,0 +1,823 @@
use std::time::Duration;
use matrix_sdk::{
config::{RequestConfig, SyncSettings},
DisplayName, RoomMember, Session,
};
use matrix_sdk_test::{async_test, test_json};
use mockito::{mock, Matcher};
use ruma::{
device_id, event_id,
events::{AnySyncStateEvent, StateEventType},
room_id, user_id,
};
use serde_json::{json, Value as JsonValue};
use crate::{logged_in_client, test_client_builder};
#[async_test]
async fn user_presence() {
let client = logged_in_client().await;
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::SYNC.to_string())
.create();
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/members".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::MEMBERS.to_string())
.create();
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
let _response = client.sync_once(sync_settings).await.unwrap();
let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap();
let members: Vec<RoomMember> = room.active_members().await.unwrap();
assert_eq!(2, members.len());
// assert!(room.power_levels.is_some())
}
#[async_test]
async fn calculate_room_names_from_summary() {
let client = logged_in_client().await;
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::DEFAULT_SYNC_SUMMARY.to_string())
.create();
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
let _response = client.sync_once(sync_settings).await.unwrap();
let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap();
assert_eq!(DisplayName::Calculated("example2".to_owned()), room.display_name().await.unwrap());
}
#[async_test]
async fn room_names() {
let client = logged_in_client().await;
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::SYNC.to_string())
.expect_at_least(1)
.create();
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
let _response = client.sync_once(sync_settings).await.unwrap();
assert_eq!(client.rooms().len(), 1);
let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap();
assert_eq!(DisplayName::Aliased("tutorial".to_owned()), room.display_name().await.unwrap());
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::INVITE_SYNC.to_string())
.expect_at_least(1)
.create();
let _response = client.sync_once(SyncSettings::new()).await.unwrap();
assert_eq!(client.rooms().len(), 1);
let invited_room = client.get_invited_room(room_id!("!696r7674:example.com")).unwrap();
assert_eq!(
DisplayName::Named("My Room Name".to_owned()),
invited_room.display_name().await.unwrap()
);
}
#[async_test]
async fn test_state_event_getting() {
let room_id = room_id!("!SVkFJHzfwvuaIEawgC:localhost");
let session = Session {
access_token: "1234".to_owned(),
user_id: user_id!("@example:localhost").to_owned(),
device_id: device_id!("DEVICEID").to_owned(),
};
let sync = json!({
"next_batch": "1234",
"rooms": {
"join": {
"!SVkFJHzfwvuaIEawgC:localhost": {
"state": {
"events": [
{
"type": "m.custom.note",
"sender": "@example:localhost",
"content": {
"body": "Note 1",
},
"state_key": "note.1",
"origin_server_ts": 1611853078727u64,
"unsigned": {
"replaces_state": "$2s9GcbVxbbFS3EZY9vN1zhavaDJnF32cAIGAxi99NuQ",
"age": 15458166523u64
},
"event_id": "$NVCTvrlxodf3ZGjJ6foxepEq8ysSkTq8wG0wKeQBVZg"
},
{
"type": "m.custom.note",
"sender": "@example2:localhost",
"content": {
"body": "Note 2",
},
"state_key": "note.2",
"origin_server_ts": 1611853078727u64,
"unsigned": {
"replaces_state": "$2s9GcbVxbbFS3EZY9vN1zhavaDJnF32cAIGAxi99NuQ",
"age": 15458166523u64
},
"event_id": "$NVCTvrlxodf3ZGjJ6foxepEq8ysSkTq8wG0wKeQBVZg"
},
{
"type": "m.room.encryption",
"sender": "@example:localhost",
"content": {
"algorithm": "m.megolm.v1.aes-sha2"
},
"state_key": "",
"origin_server_ts": 1586437448151u64,
"unsigned": {
"age": 40873797099u64
},
"event_id": "$vyG3wu1QdJSh5gc-09SwjXBXlXo8gS7s4QV_Yxha0Xw"
},
]
}
}
}
}
});
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.with_body(sync.to_string())
.create();
let client = test_client_builder()
.request_config(RequestConfig::new().retry_limit(3))
.build()
.await
.unwrap();
client.restore_login(session.clone()).await.unwrap();
let room = client.get_joined_room(room_id);
assert!(room.is_none());
client.sync_once(SyncSettings::default()).await.unwrap();
let room = client.get_joined_room(room_id).unwrap();
let state_events = room.get_state_events(StateEventType::RoomEncryption).await.unwrap();
assert_eq!(state_events.len(), 1);
let state_events = room.get_state_events("m.custom.note".into()).await.unwrap();
assert_eq!(state_events.len(), 2);
let encryption_event = room
.get_state_event(StateEventType::RoomEncryption, "")
.await
.unwrap()
.unwrap()
.deserialize()
.unwrap();
matches::assert_matches!(encryption_event, AnySyncStateEvent::RoomEncryption(_));
}
// FIXME: removing timelines during reading the stream currently leaves to an
// inconsistent undefined state. This tests shows that, but because
// different implementations deal with problem in different,
// inconsistent manners, isn't activated.
//#[async_test]
#[allow(dead_code)]
#[cfg(feature = "experimental-timeline")]
async fn room_timeline_with_remove() {
let client = logged_in_client().await;
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
let sync = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.with_body(test_json::SYNC.to_string())
.match_header("authorization", "Bearer 1234")
.create();
let _ = client.sync_once(sync_settings).await.unwrap();
sync.assert();
drop(sync);
let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap();
let (forward_stream, backward_stream) = room.timeline().await.unwrap();
// these two syncs lead to the store removing its existing timeline
// and replace them with new ones
let sync_2 = mock(
"GET",
Matcher::Regex(
r"^/_matrix/client/r0/sync\?.*since=s526_47314_0_7_1_1_1_11444_1.*".to_owned(),
),
)
.with_status(200)
.with_body(test_json::MORE_SYNC.to_string())
.match_header("authorization", "Bearer 1234")
.create();
let sync_3 = mock(
"GET",
Matcher::Regex(
r"^/_matrix/client/r0/sync\?.*since=s526_47314_0_7_1_1_1_11444_2.*".to_owned(),
),
)
.with_status(200)
.with_body(test_json::MORE_SYNC_2.to_string())
.match_header("authorization", "Bearer 1234")
.create();
let mocked_messages = mock(
"GET",
Matcher::Regex(
r"^/_matrix/client/r0/rooms/.*/messages.*from=t392-516_47314_0_7_1_1_1_11444_1.*"
.to_owned(),
),
)
.with_status(200)
.with_body(test_json::SYNC_ROOM_MESSAGES_BATCH_1.to_string())
.match_header("authorization", "Bearer 1234")
.create();
let mocked_messages_2 = mock(
"GET",
Matcher::Regex(
r"^/_matrix/client/r0/rooms/.*/messages.*from=t47409-4357353_219380_26003_2269.*"
.to_owned(),
),
)
.with_status(200)
.with_body(test_json::SYNC_ROOM_MESSAGES_BATCH_2.to_string())
.match_header("authorization", "Bearer 1234")
.create();
assert_eq!(client.sync_token().await, Some("s526_47314_0_7_1_1_1_11444_1".to_owned()));
let sync_settings = SyncSettings::new()
.timeout(Duration::from_millis(3000))
.token("s526_47314_0_7_1_1_1_11444_1");
let _ = client.sync_once(sync_settings).await.unwrap();
sync_2.assert();
let sync_settings = SyncSettings::new()
.timeout(Duration::from_millis(3000))
.token("s526_47314_0_7_1_1_1_11444_2");
let _ = client.sync_once(sync_settings).await.unwrap();
sync_3.assert();
let expected_forward_events = vec![
"$152037280074GZeOm:localhost",
"$editevid:localhost",
"$151957878228ssqrJ:localhost",
"$15275046980maRLj:localhost",
"$15275047031IXQRi:localhost",
"$098237280074GZeOm:localhost",
"$152037280074GZeOm2:localhost",
"$editevid2:localhost",
"$151957878228ssqrJ2:localhost",
"$15275046980maRLj2:localhost",
"$15275047031IXQRi2:localhost",
"$098237280074GZeOm2:localhost",
];
use futures_util::StreamExt;
use matrix_sdk::deserialized_responses::SyncRoomEvent;
let forward_events =
forward_stream.take(expected_forward_events.len()).collect::<Vec<SyncRoomEvent>>().await;
for (r, e) in forward_events.into_iter().zip(expected_forward_events.iter()) {
assert_eq!(&r.event_id().unwrap().as_str(), e);
}
let expected_backwards_events = vec![
"$152037280074GZeOm:localhost",
"$1444812213350496Caaaf:example.com",
"$1444812213350496Cbbbf:example.com",
"$1444812213350496Ccccf:example.com",
"$1444812213350496Caaak:example.com",
"$1444812213350496Cbbbk:example.com",
"$1444812213350496Cccck:example.com",
];
let backward_events = backward_stream
.take(expected_backwards_events.len())
.collect::<Vec<matrix_sdk::Result<SyncRoomEvent>>>()
.await;
for (r, e) in backward_events.into_iter().zip(expected_backwards_events.iter()) {
assert_eq!(&r.unwrap().event_id().unwrap().as_str(), e);
}
mocked_messages.assert();
mocked_messages_2.assert();
}
#[async_test]
#[cfg(feature = "experimental-timeline")]
async fn room_timeline() {
let client = logged_in_client().await;
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
let sync = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.with_body(test_json::MORE_SYNC.to_string())
.match_header("authorization", "Bearer 1234")
.create();
let _ = client.sync_once(sync_settings).await.unwrap();
sync.assert();
drop(sync);
let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap();
let (forward_stream, backward_stream) = room.timeline().await.unwrap();
let sync_2 = mock(
"GET",
Matcher::Regex(
r"^/_matrix/client/r0/sync\?.*since=s526_47314_0_7_1_1_1_11444_2.*".to_owned(),
),
)
.with_status(200)
.with_body(test_json::MORE_SYNC_2.to_string())
.match_header("authorization", "Bearer 1234")
.create();
let mocked_messages = mock(
"GET",
Matcher::Regex(
r"^/_matrix/client/r0/rooms/.*/messages.*from=t392-516_47314_0_7_1_1_1_11444_1.*"
.to_owned(),
),
)
.with_status(200)
.with_body(test_json::SYNC_ROOM_MESSAGES_BATCH_1.to_string())
.match_header("authorization", "Bearer 1234")
.create();
let mocked_messages_2 = mock(
"GET",
Matcher::Regex(
r"^/_matrix/client/r0/rooms/.*/messages.*from=t47409-4357353_219380_26003_2269.*"
.to_owned(),
),
)
.with_status(200)
.with_body(test_json::SYNC_ROOM_MESSAGES_BATCH_2.to_string())
.match_header("authorization", "Bearer 1234")
.create();
assert_eq!(client.sync_token().await, Some("s526_47314_0_7_1_1_1_11444_2".to_owned()));
let sync_settings = SyncSettings::new()
.timeout(Duration::from_millis(3000))
.token("s526_47314_0_7_1_1_1_11444_2");
let _ = client.sync_once(sync_settings).await.unwrap();
sync_2.assert();
let expected_forward_events = vec![
"$152037280074GZeOm2:localhost",
"$editevid2:localhost",
"$151957878228ssqrJ2:localhost",
"$15275046980maRLj2:localhost",
"$15275047031IXQRi2:localhost",
"$098237280074GZeOm2:localhost",
];
use futures_util::StreamExt;
use matrix_sdk::deserialized_responses::SyncRoomEvent;
let forward_events =
forward_stream.take(expected_forward_events.len()).collect::<Vec<SyncRoomEvent>>().await;
for (r, e) in forward_events.into_iter().zip(expected_forward_events.iter()) {
assert_eq!(&r.event_id().unwrap().as_str(), e);
}
let expected_backwards_events = vec![
"$098237280074GZeOm:localhost",
"$15275047031IXQRi:localhost",
"$15275046980maRLj:localhost",
"$151957878228ssqrJ:localhost",
"$editevid:localhost",
"$152037280074GZeOm:localhost",
// ^^^ These come from the first sync before we asked for the timeline and thus
// where cached
//
// While the following are fetched over the network transparently to us after,
// when scrolling back in time:
"$1444812213350496Caaaf:example.com",
"$1444812213350496Cbbbf:example.com",
"$1444812213350496Ccccf:example.com",
"$1444812213350496Caaak:example.com",
"$1444812213350496Cbbbk:example.com",
"$1444812213350496Cccck:example.com",
];
let backward_events = backward_stream
.take(expected_backwards_events.len())
.collect::<Vec<matrix_sdk::Result<SyncRoomEvent>>>()
.await;
for (r, e) in backward_events.into_iter().zip(expected_backwards_events.iter()) {
assert_eq!(&r.unwrap().event_id().unwrap().as_str(), e);
}
mocked_messages.assert();
mocked_messages_2.assert();
}
#[async_test]
async fn room_permalink() {
fn sync_response(index: u8, room_timeline_events: &[JsonValue]) -> JsonValue {
json!({
"device_one_time_keys_count": {},
"next_batch": format!("s526_47314_0_7_1_1_1_11444_{}", index + 1),
"device_lists": {
"changed": [],
"left": []
},
"account_data": {
"events": []
},
"rooms": {
"invite": {},
"join": {
"!test_room:127.0.0.1": {
"summary": {},
"account_data": {
"events": []
},
"ephemeral": {
"events": []
},
"state": {
"events": []
},
"timeline": {
"events": room_timeline_events,
"limited": false,
"prev_batch": format!("s526_47314_0_7_1_1_1_11444_{}", index - 1),
},
"unread_notifications": {
"highlight_count": 0,
"notification_count": 0,
}
}
},
"leave": {}
},
"to_device": {
"events": []
},
"presence": {
"events": []
}
})
}
fn room_member_events(nb: usize, server: &str) -> Vec<JsonValue> {
let mut events = Vec::with_capacity(nb);
for i in 0..nb {
let id = format!("${server}{i}");
let user = format!("@user{i}:{server}");
events.push(json!({
"content": {
"membership": "join",
},
"event_id": id,
"origin_server_ts": 151800140,
"sender": user,
"state_key": user,
"type": "m.room.member",
}))
}
events
}
let client = logged_in_client().await;
let sync_settings = SyncSettings::new();
// Without elligible server
let mut sync_index = 1;
let res = sync_response(
sync_index,
&[
json!({
"content": {
"creator": "@creator:127.0.0.1",
"room_version": "6",
},
"event_id": "$151957878228ekrDs",
"origin_server_ts": 15195787,
"sender": "@creator:localhost",
"state_key": "",
"type": "m.room.create",
}),
json!({
"content": {
"membership": "join",
},
"event_id": "$151800140517rfvjc",
"origin_server_ts": 151800140,
"sender": "@creator:127.0.0.1",
"state_key": "@creator:127.0.0.1",
"type": "m.room.member",
}),
],
);
let _sync = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.with_body(res.to_string())
.match_header("authorization", "Bearer 1234")
.create();
client.sync_once(sync_settings.clone()).await.unwrap();
let room = client.get_room(room_id!("!test_room:127.0.0.1")).unwrap();
assert_eq!(
room.matrix_to_permalink().await.unwrap().to_string(),
"https://matrix.to/#/%21test_room%3A127.0.0.1"
);
assert_eq!(
room.matrix_permalink(false).await.unwrap().to_string(),
"matrix:roomid/test_room:127.0.0.1"
);
assert_eq!(
room.matrix_permalink(true).await.unwrap().to_string(),
"matrix:roomid/test_room:127.0.0.1?action=join"
);
// With a single elligible server
sync_index += 1;
let res = sync_response(
sync_index,
&[json!({
"content": {
"membership": "join",
},
"event_id": "$151800140517rfvjc",
"origin_server_ts": 151800140,
"sender": "@example:localhost",
"state_key": "@example:localhost",
"type": "m.room.member",
})],
);
let _sync = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.with_body(res.to_string())
.match_header("authorization", "Bearer 1234")
.create();
client.sync_once(sync_settings.clone()).await.unwrap();
assert_eq!(
room.matrix_to_permalink().await.unwrap().to_string(),
"https://matrix.to/#/%21test_room%3A127.0.0.1?via=localhost"
);
assert_eq!(
room.matrix_permalink(false).await.unwrap().to_string(),
"matrix:roomid/test_room:127.0.0.1?via=localhost"
);
// With two elligible servers
sync_index += 1;
let res = sync_response(sync_index, &room_member_events(15, "notarealhs"));
let _sync = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.with_body(res.to_string())
.match_header("authorization", "Bearer 1234")
.create();
client.sync_once(sync_settings.clone()).await.unwrap();
assert_eq!(
room.matrix_to_permalink().await.unwrap().to_string(),
"https://matrix.to/#/%21test_room%3A127.0.0.1?via=notarealhs&via=localhost"
);
assert_eq!(
room.matrix_permalink(false).await.unwrap().to_string(),
"matrix:roomid/test_room:127.0.0.1?via=notarealhs&via=localhost"
);
// With three elligible servers
sync_index += 1;
let res = sync_response(sync_index, &room_member_events(5, "mymatrix"));
let _sync = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.with_body(res.to_string())
.match_header("authorization", "Bearer 1234")
.create();
client.sync_once(sync_settings.clone()).await.unwrap();
assert_eq!(
room.matrix_to_permalink().await.unwrap().to_string(),
"https://matrix.to/#/%21test_room%3A127.0.0.1?via=notarealhs&via=mymatrix&via=localhost"
);
assert_eq!(
room.matrix_permalink(false).await.unwrap().to_string(),
"matrix:roomid/test_room:127.0.0.1?via=notarealhs&via=mymatrix&via=localhost"
);
// With four elligible servers
sync_index += 1;
let res = sync_response(sync_index, &room_member_events(10, "yourmatrix"));
let _sync = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.with_body(res.to_string())
.match_header("authorization", "Bearer 1234")
.create();
client.sync_once(sync_settings.clone()).await.unwrap();
assert_eq!(
room.matrix_to_permalink().await.unwrap().to_string(),
"https://matrix.to/#/%21test_room%3A127.0.0.1?via=notarealhs&via=yourmatrix&via=mymatrix"
);
assert_eq!(
room.matrix_permalink(false).await.unwrap().to_string(),
"matrix:roomid/test_room:127.0.0.1?via=notarealhs&via=yourmatrix&via=mymatrix"
);
// With power levels
sync_index += 1;
let res = sync_response(
sync_index,
&[json!({
"content": {
"users": {
"@example:localhost": 50,
},
},
"event_id": "$15139375512JaHAW",
"origin_server_ts": 151393755,
"sender": "@creator:127.0.0.1",
"state_key": "",
"type": "m.room.power_levels",
})],
);
let _sync = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.with_body(res.to_string())
.match_header("authorization", "Bearer 1234")
.create();
client.sync_once(sync_settings.clone()).await.unwrap();
assert_eq!(
room.matrix_to_permalink().await.unwrap().to_string(),
"https://matrix.to/#/%21test_room%3A127.0.0.1?via=localhost&via=notarealhs&via=yourmatrix"
);
assert_eq!(
room.matrix_permalink(false).await.unwrap().to_string(),
"matrix:roomid/test_room:127.0.0.1?via=localhost&via=notarealhs&via=yourmatrix"
);
// With higher power levels
sync_index += 1;
let res = sync_response(
sync_index,
&[json!({
"content": {
"users": {
"@example:localhost": 50,
"@user0:mymatrix": 70,
},
},
"event_id": "$15139375512JaHAZ",
"origin_server_ts": 151393755,
"sender": "@creator:127.0.0.1",
"state_key": "",
"type": "m.room.power_levels",
})],
);
let _sync = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.with_body(res.to_string())
.match_header("authorization", "Bearer 1234")
.create();
client.sync_once(sync_settings.clone()).await.unwrap();
assert_eq!(
room.matrix_to_permalink().await.unwrap().to_string(),
"https://matrix.to/#/%21test_room%3A127.0.0.1?via=mymatrix&via=notarealhs&via=yourmatrix"
);
assert_eq!(
room.matrix_permalink(false).await.unwrap().to_string(),
"matrix:roomid/test_room:127.0.0.1?via=mymatrix&via=notarealhs&via=yourmatrix"
);
// With server ACLs
sync_index += 1;
let res = sync_response(
sync_index,
&[json!({
"content": {
"allow": ["*"],
"allow_ip_literals": true,
"deny": ["notarealhs"],
},
"event_id": "$143273582443PhrSn",
"origin_server_ts": 1432735824,
"sender": "@creator:127.0.0.1",
"state_key": "",
"type": "m.room.server_acl",
})],
);
let _sync = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.with_body(res.to_string())
.match_header("authorization", "Bearer 1234")
.create();
client.sync_once(sync_settings.clone()).await.unwrap();
assert_eq!(
room.matrix_to_permalink().await.unwrap().to_string(),
"https://matrix.to/#/%21test_room%3A127.0.0.1?via=mymatrix&via=yourmatrix&via=localhost"
);
assert_eq!(
room.matrix_permalink(false).await.unwrap().to_string(),
"matrix:roomid/test_room:127.0.0.1?via=mymatrix&via=yourmatrix&via=localhost"
);
// With an alternative alias
sync_index += 1;
let res = sync_response(
sync_index,
&[json!({
"content": {
"alt_aliases": ["#alias:localhost"],
},
"event_id": "$15139375513VdeRF",
"origin_server_ts": 151393755,
"sender": "@example:localhost",
"state_key": "",
"type": "m.room.canonical_alias",
})],
);
let _sync = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.with_body(res.to_string())
.match_header("authorization", "Bearer 1234")
.create();
client.sync_once(sync_settings.clone()).await.unwrap();
assert_eq!(
room.matrix_to_permalink().await.unwrap().to_string(),
"https://matrix.to/#/%23alias%3Alocalhost"
);
assert_eq!(room.matrix_permalink(false).await.unwrap().to_string(), "matrix:r/alias:localhost");
// With a canonical alias
sync_index += 1;
let res = sync_response(
sync_index,
&[json!({
"content": {
"alias": "#canonical:localhost",
"alt_aliases": ["#alias:localhost"],
},
"event_id": "$15139375513VdeRF",
"origin_server_ts": 151393755,
"sender": "@example:localhost",
"state_key": "",
"type": "m.room.canonical_alias",
})],
);
let _sync = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.with_body(res.to_string())
.match_header("authorization", "Bearer 1234")
.create();
client.sync_once(sync_settings).await.unwrap();
assert_eq!(
room.matrix_to_permalink().await.unwrap().to_string(),
"https://matrix.to/#/%23canonical%3Alocalhost"
);
assert_eq!(
room.matrix_permalink(false).await.unwrap().to_string(),
"matrix:r/canonical:localhost"
);
assert_eq!(
room.matrix_permalink(true).await.unwrap().to_string(),
"matrix:r/canonical:localhost?action=join"
);
let event_id = event_id!("$15139375512JaHAW");
assert_eq!(
room.matrix_to_event_permalink(event_id).await.unwrap().to_string(),
"https://matrix.to/#/%21test_room%3A127.0.0.1/%2415139375512JaHAW?via=mymatrix&via=yourmatrix&via=localhost"
);
assert_eq!(
room.matrix_event_permalink(event_id).await.unwrap().to_string(),
"matrix:roomid/test_room:127.0.0.1/e/15139375512JaHAW?via=mymatrix&via=yourmatrix&via=localhost"
);
}

View File

@@ -0,0 +1,569 @@
use std::{io::Cursor, time::Duration};
use matrix_sdk::{
attachment::{
AttachmentConfig, AttachmentInfo, BaseImageInfo, BaseThumbnailInfo, BaseVideoInfo,
Thumbnail,
},
config::SyncSettings,
};
use matrix_sdk_test::{async_test, test_json};
use mockito::{mock, Matcher};
use ruma::{
api::client::membership::Invite3pidInit, assign, event_id,
events::room::message::RoomMessageEventContent, mxc_uri, room_id, thirdparty, uint, user_id,
TransactionId,
};
use serde_json::json;
use crate::logged_in_client;
#[async_test]
async fn invite_user_by_id() {
let client = logged_in_client().await;
let _m = mock("POST", Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/invite".to_owned()))
.with_status(200)
.with_body(test_json::LOGOUT.to_string())
.match_header("authorization", "Bearer 1234")
.create();
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::SYNC.to_string())
.create();
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
let _response = client.sync_once(sync_settings).await.unwrap();
let user = user_id!("@example:localhost");
let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap();
room.invite_user_by_id(user).await.unwrap();
}
#[async_test]
async fn invite_user_by_3pid() {
let client = logged_in_client().await;
let _m = mock("POST", Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/invite".to_owned()))
.with_status(200)
// empty JSON object
.with_body(test_json::LOGOUT.to_string())
.match_header("authorization", "Bearer 1234")
.create();
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::SYNC.to_string())
.create();
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
let _response = client.sync_once(sync_settings).await.unwrap();
let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap();
room.invite_user_by_3pid(
Invite3pidInit {
id_server: "example.org",
id_access_token: "IdToken",
medium: thirdparty::Medium::Email,
address: "address",
}
.into(),
)
.await
.unwrap();
}
#[async_test]
async fn leave_room() {
let client = logged_in_client().await;
let _m = mock("POST", Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/leave".to_owned()))
.with_status(200)
// this is an empty JSON object
.with_body(test_json::LOGOUT.to_string())
.match_header("authorization", "Bearer 1234")
.create();
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::SYNC.to_string())
.create();
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
let _response = client.sync_once(sync_settings).await.unwrap();
let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap();
room.leave().await.unwrap();
}
#[async_test]
async fn ban_user() {
let client = logged_in_client().await;
let _m = mock("POST", Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/ban".to_owned()))
.with_status(200)
// this is an empty JSON object
.with_body(test_json::LOGOUT.to_string())
.match_header("authorization", "Bearer 1234")
.create();
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::SYNC.to_string())
.create();
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
let _response = client.sync_once(sync_settings).await.unwrap();
let user = user_id!("@example:localhost");
let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap();
room.ban_user(user, None).await.unwrap();
}
#[async_test]
async fn kick_user() {
let client = logged_in_client().await;
let _m = mock("POST", Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/kick".to_owned()))
.with_status(200)
// this is an empty JSON object
.with_body(test_json::LOGOUT.to_string())
.match_header("authorization", "Bearer 1234")
.create();
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::SYNC.to_string())
.create();
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
let _response = client.sync_once(sync_settings).await.unwrap();
let user = user_id!("@example:localhost");
let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap();
room.kick_user(user, None).await.unwrap();
}
#[async_test]
async fn read_receipt() {
let client = logged_in_client().await;
let _m = mock("POST", Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/receipt".to_owned()))
.with_status(200)
// this is an empty JSON object
.with_body(test_json::LOGOUT.to_string())
.match_header("authorization", "Bearer 1234")
.create();
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::SYNC.to_string())
.create();
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
let _response = client.sync_once(sync_settings).await.unwrap();
let event_id = event_id!("$xxxxxx:example.org");
let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap();
room.read_receipt(event_id).await.unwrap();
}
#[async_test]
async fn read_marker() {
let client = logged_in_client().await;
let _m = mock("POST", Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/read_markers".to_owned()))
.with_status(200)
// this is an empty JSON object
.with_body(test_json::LOGOUT.to_string())
.match_header("authorization", "Bearer 1234")
.create();
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::SYNC.to_string())
.create();
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
let _response = client.sync_once(sync_settings).await.unwrap();
let event_id = event_id!("$xxxxxx:example.org");
let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap();
room.read_marker(event_id, None).await.unwrap();
}
#[async_test]
async fn typing_notice() {
let client = logged_in_client().await;
let _m = mock("PUT", Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/typing".to_owned()))
.with_status(200)
// this is an empty JSON object
.with_body(test_json::LOGOUT.to_string())
.match_header("authorization", "Bearer 1234")
.create();
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::SYNC.to_string())
.create();
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
let _response = client.sync_once(sync_settings).await.unwrap();
let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap();
room.typing_notice(true).await.unwrap();
}
#[async_test]
async fn room_state_event_send() {
use ruma::events::room::member::{MembershipState, RoomMemberEventContent};
let client = logged_in_client().await;
let _m = mock("PUT", Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/state/.*".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::EVENT_ID.to_string())
.create();
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::SYNC.to_string())
.create();
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
let _response = client.sync_once(sync_settings).await.unwrap();
let room_id = room_id!("!SVkFJHzfwvuaIEawgC:localhost");
let room = client.get_joined_room(room_id).unwrap();
let avatar_url = mxc_uri!("mxc://example.org/avA7ar");
let member_event = assign!(RoomMemberEventContent::new(MembershipState::Join), {
avatar_url: Some(avatar_url.to_owned())
});
let response = room.send_state_event(member_event, "").await.unwrap();
assert_eq!(event_id!("$h29iv0s8:example.com"), response.event_id);
}
#[async_test]
async fn room_message_send() {
let client = logged_in_client().await;
let _m = mock("PUT", Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/send/".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::EVENT_ID.to_string())
.create();
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::SYNC.to_string())
.create();
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
let _response = client.sync_once(sync_settings).await.unwrap();
let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap();
let content = RoomMessageEventContent::text_plain("Hello world");
let txn_id = TransactionId::new();
let response = room.send(content, Some(&txn_id)).await.unwrap();
assert_eq!(event_id!("$h29iv0s8:example.com"), response.event_id)
}
#[async_test]
async fn room_attachment_send() {
let client = logged_in_client().await;
let _m = mock("PUT", Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/send/".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.match_body(Matcher::PartialJson(json!({
"info": {
"mimetype": "image/jpeg"
}
})))
.with_body(test_json::EVENT_ID.to_string())
.create();
let _m = mock("POST", Matcher::Regex(r"^/_matrix/media/r0/upload".to_owned()))
.with_status(200)
.match_header("content-type", "image/jpeg")
.with_body(
json!({
"content_uri": "mxc://example.com/AQwafuaFswefuhsfAFAgsw"
})
.to_string(),
)
.create();
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::SYNC.to_string())
.create();
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
let _response = client.sync_once(sync_settings).await.unwrap();
let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap();
let mut media = Cursor::new("Hello world");
let response = room
.send_attachment("image", &mime::IMAGE_JPEG, &mut media, AttachmentConfig::new())
.await
.unwrap();
assert_eq!(event_id!("$h29iv0s8:example.com"), response.event_id)
}
#[async_test]
async fn room_attachment_send_info() {
let client = logged_in_client().await;
let _m = mock("PUT", Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/send/".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.match_body(Matcher::PartialJson(json!({
"info": {
"mimetype": "image/jpeg",
"h": 600,
"w": 800,
}
})))
.with_body(test_json::EVENT_ID.to_string())
.create();
let upload_mock = mock("POST", Matcher::Regex(r"^/_matrix/media/r0/upload".to_owned()))
.with_status(200)
.match_header("content-type", "image/jpeg")
.with_body(
json!({
"content_uri": "mxc://example.com/AQwafuaFswefuhsfAFAgsw"
})
.to_string(),
)
.create();
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::SYNC.to_string())
.create();
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
let _response = client.sync_once(sync_settings).await.unwrap();
let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap();
let mut media = Cursor::new("Hello world");
let config = AttachmentConfig::new().info(AttachmentInfo::Image(BaseImageInfo {
height: Some(uint!(600)),
width: Some(uint!(800)),
size: None,
blurhash: None,
}));
let response =
room.send_attachment("image", &mime::IMAGE_JPEG, &mut media, config).await.unwrap();
upload_mock.assert();
assert_eq!(event_id!("$h29iv0s8:example.com"), response.event_id)
}
#[async_test]
async fn room_attachment_send_wrong_info() {
let client = logged_in_client().await;
let _m = mock("PUT", Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/send/".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.match_body(Matcher::PartialJson(json!({
"info": {
"mimetype": "image/jpeg",
"h": 600,
"w": 800,
}
})))
.with_body(test_json::EVENT_ID.to_string())
.create();
let _m = mock("POST", Matcher::Regex(r"^/_matrix/media/r0/upload".to_owned()))
.with_status(200)
.match_header("content-type", "image/jpeg")
.with_body(
json!({
"content_uri": "mxc://example.com/AQwafuaFswefuhsfAFAgsw"
})
.to_string(),
)
.create();
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::SYNC.to_string())
.create();
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
let _response = client.sync_once(sync_settings).await.unwrap();
let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap();
let mut media = Cursor::new("Hello world");
let config = AttachmentConfig::new().info(AttachmentInfo::Video(BaseVideoInfo {
height: Some(uint!(600)),
width: Some(uint!(800)),
duration: Some(Duration::from_millis(3600)),
size: None,
blurhash: None,
}));
let response = room.send_attachment("image", &mime::IMAGE_JPEG, &mut media, config).await;
assert!(response.is_err())
}
#[async_test]
async fn room_attachment_send_info_thumbnail() {
let client = logged_in_client().await;
let _m = mock("PUT", Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/send/".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.match_body(Matcher::PartialJson(json!({
"info": {
"mimetype": "image/jpeg",
"h": 600,
"w": 800,
"thumbnail_info": {
"h": 360,
"w": 480,
"mimetype":"image/jpeg",
"size": 3600,
},
"thumbnail_url": "mxc://example.com/AQwafuaFswefuhsfAFAgsw",
}
})))
.with_body(test_json::EVENT_ID.to_string())
.create();
let upload_mock = mock("POST", Matcher::Regex(r"^/_matrix/media/r0/upload".to_owned()))
.with_status(200)
.match_header("content-type", "image/jpeg")
.with_body(
json!({
"content_uri": "mxc://example.com/AQwafuaFswefuhsfAFAgsw"
})
.to_string(),
)
.expect(2)
.create();
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::SYNC.to_string())
.create();
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
let _response = client.sync_once(sync_settings).await.unwrap();
let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap();
let mut media = Cursor::new("Hello world");
let mut thumbnail_reader = Cursor::new("Thumbnail");
let config = AttachmentConfig::with_thumbnail(Thumbnail {
reader: &mut thumbnail_reader,
content_type: &mime::IMAGE_JPEG,
info: Some(BaseThumbnailInfo {
height: Some(uint!(360)),
width: Some(uint!(480)),
size: Some(uint!(3600)),
}),
})
.info(AttachmentInfo::Image(BaseImageInfo {
height: Some(uint!(600)),
width: Some(uint!(800)),
size: None,
blurhash: None,
}));
let response =
room.send_attachment("image", &mime::IMAGE_JPEG, &mut media, config).await.unwrap();
upload_mock.assert();
assert_eq!(event_id!("$h29iv0s8:example.com"), response.event_id)
}
#[async_test]
async fn room_redact() {
let client = logged_in_client().await;
let _m = mock("PUT", Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/redact/.*?/.*?".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::EVENT_ID.to_string())
.create();
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::SYNC.to_string())
.create();
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
let _response = client.sync_once(sync_settings).await.unwrap();
let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap();
let event_id = event_id!("$xxxxxxxx:example.com");
let txn_id = TransactionId::new();
let reason = Some("Indecent material");
let response = room.redact(event_id, reason, Some(txn_id)).await.unwrap();
assert_eq!(event_id!("$h29iv0s8:example.com"), response.event_id)
}

View File

@@ -0,0 +1,34 @@
use std::time::Duration;
use matrix_sdk::config::SyncSettings;
use matrix_sdk_test::{async_test, test_json};
use mockito::{mock, Matcher};
use ruma::room_id;
use crate::logged_in_client;
#[async_test]
async fn forget_room() {
let client = logged_in_client().await;
let _m = mock("POST", Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/forget".to_owned()))
.with_status(200)
// this is an empty JSON object
.with_body(test_json::LOGOUT.to_string())
.match_header("authorization", "Bearer 1234")
.create();
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_owned()))
.with_status(200)
.match_header("authorization", "Bearer 1234")
.with_body(test_json::LEAVE_SYNC.to_string())
.create();
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
let _response = client.sync_once(sync_settings).await.unwrap();
let room = client.get_left_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap();
room.forget().await.unwrap();
}

View File

@@ -0,0 +1,3 @@
mod common;
mod joined;
mod left;