diff --git a/src/chat/chat_tests.rs b/src/chat/chat_tests.rs index aa92ef693..5542c676a 100644 --- a/src/chat/chat_tests.rs +++ b/src/chat/chat_tests.rs @@ -3846,8 +3846,13 @@ async fn test_sync_broadcast() -> Result<()> { assert_eq!(a1_broadcast_chat.get_type(), Chattype::OutBroadcast); assert_eq!(a1_broadcast_chat.get_name(), a0_broadcast_chat.get_name()); assert!(get_chat_contacts(alice1, a1_broadcast_id).await?.is_empty()); - add_contact_to_chat(alice0, a0_broadcast_id, a0b_contact_id).await?; - sync(alice0, alice1).await; + + let qr = get_securejoin_qr(alice0, Some(a0_broadcast_id)) + .await + .unwrap(); + sync(alice0, alice1).await; // Sync QR code + tcm.exec_securejoin_qr_multi_device(bob, &[alice0, alice1], &qr) + .await; // This also imports Bob's key from the vCard. // Otherwise it is possible that second device diff --git a/src/securejoin.rs b/src/securejoin.rs index d41d086f0..69476639b 100644 --- a/src/securejoin.rs +++ b/src/securejoin.rs @@ -99,6 +99,13 @@ pub async fn get_securejoin_qr(context: &Context, chat: Option) -> Resul utf8_percent_encode(&self_name, NON_ALPHANUMERIC_WITHOUT_DOT).to_string(); let qr = if let Some(chat) = chat { + if sync_token { + context + .sync_qr_code_tokens(Some(chat.grpid.as_str())) + .await?; + context.scheduler.interrupt_inbox().await; + } + if chat.typ == Chattype::OutBroadcast { let broadcast_name = chat.get_name(); let broadcast_name_urlencoded = @@ -106,7 +113,6 @@ pub async fn get_securejoin_qr(context: &Context, chat: Option) -> Resul let broadcast_secret = load_broadcast_shared_secret(context, chat.id) .await? .context("Could not find broadcast secret")?; - format!( "https://i.delta.chat/#{}&a={}&g={}&x={}&s={}&b={}", fingerprint.hex(), @@ -121,12 +127,6 @@ pub async fn get_securejoin_qr(context: &Context, chat: Option) -> Resul let group_name = chat.get_name(); let group_name_urlencoded = utf8_percent_encode(group_name, NON_ALPHANUMERIC).to_string(); - if sync_token { - context - .sync_qr_code_tokens(Some(chat.grpid.as_str())) - .await?; - context.scheduler.interrupt_inbox().await; - } format!( "https://i.delta.chat/#{}&a={}&g={}&x={}&i={}&s={}", fingerprint.hex(), diff --git a/src/test_utils.rs b/src/test_utils.rs index c6c772cf9..c2aef7408 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -228,18 +228,42 @@ impl TestContextManager { /// chat with `scanned`, for a SecureJoin QR this is the group chat. pub async fn exec_securejoin_qr( &self, - scanner: &TestContext, + joiner: &TestContext, inviter: &TestContext, qr: &str, ) -> ChatId { - let chat_id = join_securejoin(&scanner.ctx, qr).await.unwrap(); + self.exec_securejoin_qr_multi_device(joiner, &[inviter], qr) + .await + } + + /// Executes SecureJoin initiated by `scanner` scanning `qr` generated by `scanned`. + /// + /// The [`ChatId`] of the created chat is returned, for a SetupContact QR this is the 1:1 + /// chat with `scanned`, for a SecureJoin QR this is the group chat. + pub async fn exec_securejoin_qr_multi_device( + &self, + joiner: &TestContext, + inviters: &[&TestContext], + qr: &str, + ) -> ChatId { + let chat_id = join_securejoin(&joiner.ctx, qr).await.unwrap(); loop { - if let Some(sent) = scanner.pop_sent_msg_opt(Duration::ZERO).await { - inviter.recv_msg_opt(&sent).await; - } else if let Some(sent) = inviter.pop_sent_msg_opt(Duration::ZERO).await { - scanner.recv_msg_opt(&sent).await; - } else { + let mut something_sent = false; + if let Some(sent) = joiner.pop_sent_msg_opt(Duration::ZERO).await { + for inviter in inviters { + inviter.recv_msg_opt(&sent).await; + } + something_sent = true; + } + for inviter in inviters { + if let Some(sent) = inviter.pop_sent_msg_opt(Duration::ZERO).await { + joiner.recv_msg_opt(&sent).await; + something_sent = true; + } + } + + if !something_sent { break; } }