mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-09-01 13:04:08 +00:00
114 lines
3.8 KiB
Rust
114 lines
3.8 KiB
Rust
use super::{init_tracing, Tester};
|
|
use rust_lib_twonly::api::Server;
|
|
use rust_lib_twonly::bridge::api::ApiConnectionState;
|
|
use rust_lib_twonly::database::app::tables::Group;
|
|
use rust_lib_twonly::services::contacts::ContactService;
|
|
use rust_lib_twonly::services::messages::MessageService;
|
|
|
|
async fn create_authenticated_tester() -> anyhow::Result<Tester> {
|
|
let mut tester = Tester::new().await?;
|
|
tester.wait_until(ApiConnectionState::Connected).await?;
|
|
tester.register_and_authenticate().await?;
|
|
tester.wait_until(ApiConnectionState::Authenticated).await?;
|
|
Ok(tester)
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_contact_cross_request_auto_accept() -> anyhow::Result<()> {
|
|
init_tracing();
|
|
let tester_a = create_authenticated_tester().await?;
|
|
let tester_b = create_authenticated_tester().await?;
|
|
|
|
// Tester A requests Tester B
|
|
ContactService::new(&tester_a.context)
|
|
.request_by_username(tester_b.username.clone(), true)
|
|
.await?;
|
|
|
|
// Wait until Tester B sees the incoming request
|
|
tester_b
|
|
.wait_for_contact_state(tester_a.user_id, false, true)
|
|
.await?;
|
|
|
|
// Tester B also sends a request to Tester A (instead of explicitly clicking accept)
|
|
ContactService::new(&tester_b.context)
|
|
.request_by_username(tester_a.username.clone(), true)
|
|
.await?;
|
|
|
|
// Both should auto-accept and become accepted contacts
|
|
tester_a
|
|
.wait_for_contact_state(tester_b.user_id, true, false)
|
|
.await?;
|
|
tester_b
|
|
.wait_for_contact_state(tester_a.user_id, true, false)
|
|
.await?;
|
|
|
|
// Verify direct chat group exists on both
|
|
let group_id = Group::direct_chat_id(tester_a.user_id, tester_b.user_id);
|
|
let msg_id = MessageService::new(&tester_a.context)
|
|
.insert_and_send_text(group_id.clone(), "Hello after cross-request!".into(), None)
|
|
.await?;
|
|
tester_b
|
|
.wait_for_text_message(&msg_id, tester_a.user_id, "Hello after cross-request!")
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_unknown_sender_auto_contact_discovery() -> anyhow::Result<()> {
|
|
init_tracing();
|
|
let tester_a = create_authenticated_tester().await?;
|
|
let tester_b = create_authenticated_tester().await?;
|
|
|
|
// Tester A requests Tester B by username and gets prekeys to establish session
|
|
ContactService::new(&tester_a.context)
|
|
.request_by_username(tester_b.username.clone(), true)
|
|
.await?;
|
|
|
|
// Verify Tester B now automatically has Tester A in contacts and signal_identities
|
|
tester_b
|
|
.wait_for_contact_username(tester_a.user_id, &tester_a.username)
|
|
.await?;
|
|
|
|
let signal_db_b = tester_b.context.rust_db.read().await.clone();
|
|
let identity_exists = sqlx::query_scalar!(
|
|
"SELECT EXISTS(SELECT 1 FROM signal_identities WHERE name = ?)",
|
|
tester_a.user_id.to_string(),
|
|
)
|
|
.fetch_one(&signal_db_b.pool)
|
|
.await?;
|
|
assert_eq!(
|
|
identity_exists, 1,
|
|
"signal identity must be recorded for unknown sender"
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_check_for_deleted_usernames() -> anyhow::Result<()> {
|
|
init_tracing();
|
|
let tester_a = create_authenticated_tester().await?;
|
|
let tester_b = create_authenticated_tester().await?;
|
|
|
|
// Tester A manually inserts Tester B with '[deleted]' username placeholder
|
|
{
|
|
let db_a = tester_a.context.app_db.read().await.clone();
|
|
sqlx::query!(
|
|
"INSERT INTO contacts(user_id, username, accepted, requested) VALUES (?, '[deleted]', 1, 0)",
|
|
tester_b.user_id,
|
|
)
|
|
.execute(&db_a.pool)
|
|
.await?;
|
|
}
|
|
|
|
// Call check_for_deleted_usernames
|
|
Server::check_for_deleted_usernames(&tester_a.context).await?;
|
|
|
|
// Verify username was restored from the server
|
|
tester_a
|
|
.wait_for_contact_username(tester_b.user_id, &tester_b.username)
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|