mirror of
https://github.com/chatmail/core.git
synced 2026-04-17 21:46:35 +03:00
Adds an api to get all ui config keys. There already is an option to get all normal config keys (`"sys.config_keys"`), but before this pr there was no way to get all `ui.*` config keys. #### Why is this api needed? For webxdc cleanup on desktop, which stores window position in a ui config key (such as `ui.desktop.webxdcBounds.676464`) as soon as a webxdc is opened since many versions now. So listing all ui keys is a good way for us to find out which webxdc may have web data stored. unfortunately electron does not (yet?) have a way to list all origins that have web-data like android does, so this is the next best thing we can do before itterating all possible ids, see also https://github.com/deltachat/deltachat-desktop/issues/5758. #### Why is this only a jsonrpc api and not another special/virtual config key like `"sys.config_keys"`? r10s indicated that `ui.*`-config keys are barely used (https://github.com/deltachat/deltachat-desktop/issues/5790#issuecomment-3598512802), so I thought it makes more sense to add it as dedicated api which's existentence is checked by the typechecker, so it will be easier to not miss it when we should remove the api again in the future. But we could also do a dedicated special/virtual config key for it, if you think that is better, this is easy to change. --------- Co-authored-by: iequidoo <117991069+iequidoo@users.noreply.github.com>
377 lines
12 KiB
Rust
377 lines
12 KiB
Rust
use num_traits::FromPrimitive;
|
|
|
|
use super::*;
|
|
use crate::test_utils::{TestContext, TestContextManager, sync};
|
|
|
|
#[test]
|
|
fn test_to_string() {
|
|
assert_eq!(Config::MailServer.to_string(), "mail_server");
|
|
assert_eq!(Config::from_str("mail_server"), Ok(Config::MailServer));
|
|
|
|
assert_eq!(Config::SysConfigKeys.to_string(), "sys.config_keys");
|
|
assert_eq!(
|
|
Config::from_str("sys.config_keys"),
|
|
Ok(Config::SysConfigKeys)
|
|
);
|
|
}
|
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
|
async fn test_set_config_addr() {
|
|
let t = TestContext::new().await;
|
|
|
|
// Test that uppercase address get lowercased.
|
|
assert!(
|
|
t.set_config(Config::Addr, Some("Foobar@eXample.oRg"))
|
|
.await
|
|
.is_ok()
|
|
);
|
|
assert_eq!(
|
|
t.get_config(Config::Addr).await.unwrap().unwrap(),
|
|
"foobar@example.org"
|
|
);
|
|
}
|
|
|
|
/// Tests that "bot" config can only be set to "0" or "1".
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
|
async fn test_set_config_bot() {
|
|
let t = TestContext::new().await;
|
|
|
|
assert!(t.set_config(Config::Bot, None).await.is_ok());
|
|
assert!(t.set_config(Config::Bot, Some("0")).await.is_ok());
|
|
assert!(t.set_config(Config::Bot, Some("1")).await.is_ok());
|
|
assert!(t.set_config(Config::Bot, Some("2")).await.is_err());
|
|
assert!(t.set_config(Config::Bot, Some("Foobar")).await.is_err());
|
|
}
|
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
|
async fn test_media_quality_config_option() {
|
|
let t = TestContext::new().await;
|
|
let media_quality = t.get_config_int(Config::MediaQuality).await.unwrap();
|
|
assert_eq!(media_quality, 0);
|
|
let media_quality = constants::MediaQuality::from_i32(media_quality).unwrap_or_default();
|
|
assert_eq!(media_quality, constants::MediaQuality::Balanced);
|
|
|
|
t.set_config(Config::MediaQuality, Some("1")).await.unwrap();
|
|
|
|
let media_quality = t.get_config_int(Config::MediaQuality).await.unwrap();
|
|
assert_eq!(media_quality, 1);
|
|
assert_eq!(constants::MediaQuality::Worse as i32, 1);
|
|
let media_quality = constants::MediaQuality::from_i32(media_quality).unwrap_or_default();
|
|
assert_eq!(media_quality, constants::MediaQuality::Worse);
|
|
}
|
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
|
async fn test_ui_config() -> Result<()> {
|
|
let t = TestContext::new().await;
|
|
|
|
assert_eq!(t.get_ui_config("ui.desktop.linux.systray").await?, None);
|
|
|
|
t.set_ui_config("ui.android.screen_security", Some("safe"))
|
|
.await?;
|
|
assert_eq!(
|
|
t.get_ui_config("ui.android.screen_security").await?,
|
|
Some("safe".to_string())
|
|
);
|
|
|
|
t.set_ui_config("ui.android.screen_security", None).await?;
|
|
assert_eq!(t.get_ui_config("ui.android.screen_security").await?, None);
|
|
|
|
assert!(t.set_ui_config("configured", Some("bar")).await.is_err());
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
|
async fn test_get_all_ui_config_keys() -> Result<()> {
|
|
let t = TestContext::new().await;
|
|
|
|
t.set_ui_config("ui.android.screen_security", Some("safe"))
|
|
.await?;
|
|
t.set_ui_config("ui.lastchatid", Some("231")).await?;
|
|
t.set_ui_config(
|
|
"ui.desktop.webxdcBounds.528490",
|
|
Some(r#"{"x":954,"y":356,"width":378,"height":671}"#),
|
|
)
|
|
.await?;
|
|
t.set_ui_config(
|
|
"ui.desktop.webxdcBounds.556543",
|
|
Some(r#"{"x":954,"y":356,"width":378,"height":671}"#),
|
|
)
|
|
.await?;
|
|
|
|
assert_eq!(
|
|
get_all_ui_config_keys(&t).await?,
|
|
vec![
|
|
"ui.android.screen_security",
|
|
"ui.lastchatid",
|
|
"ui.desktop.webxdcBounds.528490",
|
|
"ui.desktop.webxdcBounds.556543"
|
|
]
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Regression test for https://github.com/deltachat/deltachat-core-rust/issues/3012
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
|
async fn test_set_config_bool() -> Result<()> {
|
|
let t = TestContext::new().await;
|
|
|
|
// We need some config that defaults to true
|
|
let c = Config::MdnsEnabled;
|
|
assert_eq!(t.get_config_bool(c).await?, true);
|
|
t.set_config_bool(c, false).await?;
|
|
assert_eq!(t.get_config_bool(c).await?, false);
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
|
async fn test_mdns_default_behaviour() -> Result<()> {
|
|
let t = &TestContext::new_alice().await;
|
|
assert!(t.should_request_mdns().await?);
|
|
assert!(t.should_send_mdns().await?);
|
|
assert!(t.get_config_bool_opt(Config::MdnsEnabled).await?.is_none());
|
|
// The setting should be displayed correctly.
|
|
assert!(t.get_config_bool(Config::MdnsEnabled).await?);
|
|
|
|
t.set_config_bool(Config::Bot, true).await?;
|
|
assert!(!t.should_request_mdns().await?);
|
|
assert!(t.should_send_mdns().await?);
|
|
assert!(t.get_config_bool_opt(Config::MdnsEnabled).await?.is_none());
|
|
assert!(t.get_config_bool(Config::MdnsEnabled).await?);
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
|
async fn test_delete_server_after_default() -> Result<()> {
|
|
let t = &TestContext::new_alice().await;
|
|
|
|
// Check that the settings are displayed correctly.
|
|
assert_eq!(t.get_config(Config::BccSelf).await?, Some("1".to_string()));
|
|
assert_eq!(
|
|
t.get_config(Config::DeleteServerAfter).await?,
|
|
Some("0".to_string())
|
|
);
|
|
|
|
// Leaving emails on the server even w/o `BccSelf` is a good default at least because other
|
|
// MUAs do so even if the server doesn't save sent messages to some sentbox (like Gmail
|
|
// does).
|
|
t.set_config_bool(Config::BccSelf, false).await?;
|
|
assert_eq!(
|
|
t.get_config(Config::DeleteServerAfter).await?,
|
|
Some("0".to_string())
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
const SAVED_MESSAGES_DEDUPLICATED_FILE: &str = "969142cb84015bc135767bc2370934a.png";
|
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
|
async fn test_sync() -> Result<()> {
|
|
let alice0 = TestContext::new_alice().await;
|
|
let alice1 = TestContext::new_alice().await;
|
|
for a in [&alice0, &alice1] {
|
|
a.set_config_bool(Config::SyncMsgs, true).await?;
|
|
}
|
|
|
|
let mdns_enabled = alice0.get_config_bool(Config::MdnsEnabled).await?;
|
|
// Alice1 has a different config value.
|
|
alice1
|
|
.set_config_bool(Config::MdnsEnabled, !mdns_enabled)
|
|
.await?;
|
|
// This changes nothing, but still sends a sync message.
|
|
alice0
|
|
.set_config_bool(Config::MdnsEnabled, mdns_enabled)
|
|
.await?;
|
|
sync(&alice0, &alice1).await;
|
|
assert_eq!(
|
|
alice1.get_config_bool(Config::MdnsEnabled).await?,
|
|
mdns_enabled
|
|
);
|
|
|
|
// Reset to default. Test that it's not synced because defaults may differ across client
|
|
// versions.
|
|
alice0.set_config(Config::MdnsEnabled, None).await?;
|
|
alice0.set_config_bool(Config::MdnsEnabled, false).await?;
|
|
sync(&alice0, &alice1).await;
|
|
assert_eq!(alice1.get_config_bool(Config::MdnsEnabled).await?, false);
|
|
|
|
for key in [Config::ShowEmails, Config::MvboxMove] {
|
|
let val = alice0.get_config_bool(key).await?;
|
|
alice0.set_config_bool(key, !val).await?;
|
|
sync(&alice0, &alice1).await;
|
|
assert_eq!(alice1.get_config_bool(key).await?, !val);
|
|
}
|
|
|
|
// `Config::SyncMsgs` mustn't be synced.
|
|
alice0.set_config_bool(Config::SyncMsgs, false).await?;
|
|
alice0.set_config_bool(Config::SyncMsgs, true).await?;
|
|
alice0.set_config_bool(Config::MdnsEnabled, true).await?;
|
|
sync(&alice0, &alice1).await;
|
|
assert!(alice1.get_config_bool(Config::MdnsEnabled).await?);
|
|
|
|
// Usual sync scenario.
|
|
async fn test_config_str(
|
|
alice0: &TestContext,
|
|
alice1: &TestContext,
|
|
key: Config,
|
|
val: &str,
|
|
) -> Result<()> {
|
|
alice0.set_config(key, Some(val)).await?;
|
|
sync(alice0, alice1).await;
|
|
assert_eq!(alice1.get_config(key).await?, Some(val.to_string()));
|
|
Ok(())
|
|
}
|
|
test_config_str(&alice0, &alice1, Config::Displayname, "Alice Sync").await?;
|
|
test_config_str(&alice0, &alice1, Config::Selfstatus, "My status").await?;
|
|
|
|
assert!(alice0.get_config(Config::Selfavatar).await?.is_none());
|
|
let file = alice0.dir.path().join("avatar.png");
|
|
let bytes = include_bytes!("../../test-data/image/avatar64x64.png");
|
|
tokio::fs::write(&file, bytes).await?;
|
|
alice0
|
|
.set_config(Config::Selfavatar, Some(file.to_str().unwrap()))
|
|
.await?;
|
|
sync(&alice0, &alice1).await;
|
|
// There was a bug that a sync message creates the self-chat with the user avatar instead of
|
|
// the special icon and that remains so when the self-chat becomes user-visible. Let's check
|
|
// this.
|
|
let self_chat = alice0.get_self_chat().await;
|
|
let self_chat_avatar_path = self_chat.get_profile_image(&alice0).await?.unwrap();
|
|
assert_eq!(
|
|
self_chat_avatar_path,
|
|
alice0.get_blobdir().join(SAVED_MESSAGES_DEDUPLICATED_FILE)
|
|
);
|
|
assert!(
|
|
alice1
|
|
.get_config(Config::Selfavatar)
|
|
.await?
|
|
.filter(|path| path.ends_with(".png"))
|
|
.is_some()
|
|
);
|
|
alice0.set_config(Config::Selfavatar, None).await?;
|
|
sync(&alice0, &alice1).await;
|
|
assert!(alice1.get_config(Config::Selfavatar).await?.is_none());
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
|
async fn test_no_sync_on_self_sent_msg() -> Result<()> {
|
|
let mut tcm = TestContextManager::new();
|
|
let alice0 = &tcm.alice().await;
|
|
let alice1 = &tcm.alice().await;
|
|
for a in [alice0, alice1] {
|
|
a.set_config_bool(Config::SyncMsgs, true).await?;
|
|
}
|
|
|
|
let status = "Sent via usual message";
|
|
alice0.set_config(Config::Selfstatus, Some(status)).await?;
|
|
alice0.send_sync_msg().await?;
|
|
alice0.pop_sent_msg().await;
|
|
let status1 = "Synced via sync message";
|
|
alice1.set_config(Config::Selfstatus, Some(status1)).await?;
|
|
tcm.send_recv(alice0, alice1, "hi Alice!").await;
|
|
assert_eq!(
|
|
alice1.get_config(Config::Selfstatus).await?,
|
|
Some(status1.to_string())
|
|
);
|
|
sync(alice1, alice0).await;
|
|
assert_eq!(
|
|
alice0.get_config(Config::Selfstatus).await?,
|
|
Some(status1.to_string())
|
|
);
|
|
|
|
// Need a chat with another contact to send self-avatar.
|
|
let bob = &tcm.bob().await;
|
|
let a0b_chat_id = tcm.send_recv_accept(bob, alice0, "hi").await.chat_id;
|
|
let file = alice0.dir.path().join("avatar.png");
|
|
let bytes = include_bytes!("../../test-data/image/avatar64x64.png");
|
|
tokio::fs::write(&file, bytes).await?;
|
|
alice0
|
|
.set_config(Config::Selfavatar, Some(file.to_str().unwrap()))
|
|
.await?;
|
|
alice0.send_sync_msg().await?;
|
|
alice0.pop_sent_msg().await;
|
|
let file = alice1.dir.path().join("avatar.jpg");
|
|
let bytes = include_bytes!("../../test-data/image/avatar1000x1000.jpg");
|
|
tokio::fs::write(&file, bytes).await?;
|
|
alice1
|
|
.set_config(Config::Selfavatar, Some(file.to_str().unwrap()))
|
|
.await?;
|
|
let sent_msg = alice0.send_text(a0b_chat_id, "hi").await;
|
|
alice1.recv_msg(&sent_msg).await;
|
|
assert!(
|
|
alice1
|
|
.get_config(Config::Selfavatar)
|
|
.await?
|
|
.filter(|path| path.ends_with(".jpg"))
|
|
.is_some()
|
|
);
|
|
sync(alice1, alice0).await;
|
|
assert!(
|
|
alice0
|
|
.get_config(Config::Selfavatar)
|
|
.await?
|
|
.filter(|path| path.ends_with(".jpg"))
|
|
.is_some()
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
|
async fn test_event_config_synced() -> Result<()> {
|
|
let alice0 = TestContext::new_alice().await;
|
|
let alice1 = TestContext::new_alice().await;
|
|
for a in [&alice0, &alice1] {
|
|
a.set_config_bool(Config::SyncMsgs, true).await?;
|
|
}
|
|
|
|
alice0
|
|
.set_config(Config::Displayname, Some("Alice Sync"))
|
|
.await?;
|
|
alice0
|
|
.evtracker
|
|
.get_matching(|e| {
|
|
matches!(
|
|
e,
|
|
EventType::ConfigSynced {
|
|
key: Config::Displayname
|
|
}
|
|
)
|
|
})
|
|
.await;
|
|
sync(&alice0, &alice1).await;
|
|
assert_eq!(
|
|
alice1.get_config(Config::Displayname).await?,
|
|
Some("Alice Sync".to_string())
|
|
);
|
|
alice1
|
|
.evtracker
|
|
.get_matching(|e| {
|
|
matches!(
|
|
e,
|
|
EventType::ConfigSynced {
|
|
key: Config::Displayname
|
|
}
|
|
)
|
|
})
|
|
.await;
|
|
|
|
alice0.set_config(Config::Displayname, None).await?;
|
|
alice0
|
|
.evtracker
|
|
.get_matching(|e| {
|
|
matches!(
|
|
e,
|
|
EventType::ConfigSynced {
|
|
key: Config::Displayname
|
|
}
|
|
)
|
|
})
|
|
.await;
|
|
|
|
Ok(())
|
|
}
|