1use crate::sync::engine::LoginsSyncEngine;
6use crate::LoginStore;
7use anyhow::Result;
8use std::sync::Arc;
9
10impl LoginStore {
11 pub fn bridged_engine(self: Arc<Self>) -> Result<Arc<LoginsBridgedEngine>> {
18 let engine = LoginsSyncEngine::new(self)?;
19 Ok(Arc::new(LoginsBridgedEngine::new(Box::new(engine))))
20 }
21}
22
23sync15::uniffi_bridged_engine!(LoginsBridgedEngine);
28
29#[cfg(not(feature = "keydb"))]
30#[cfg(test)]
31mod tests {
32 use super::*;
33 use crate::db::test_utils::insert_login;
34 use nss_as::ensure_initialized;
35 use std::collections::HashMap;
36
37 #[test]
41 fn test_sync_meta() {
42 ensure_initialized();
43 error_support::init_for_tests();
44
45 let store = Arc::new(LoginStore::new_in_memory());
46 let bridge = store.bridged_engine().expect("should create bridge");
47
48 assert_eq!(bridge.last_sync().unwrap(), 0);
50 bridge.set_uploaded(3, vec![]).unwrap();
51 assert_eq!(bridge.last_sync().unwrap(), 3);
52
53 assert!(bridge.sync_id().unwrap().is_none());
54
55 bridge.ensure_current_sync_id("some_guid").unwrap();
56 assert_eq!(bridge.sync_id().unwrap(), Some("some_guid".to_string()));
57 assert_eq!(bridge.last_sync().unwrap(), 0);
59 bridge.set_uploaded(3, vec![]).unwrap();
61
62 bridge.reset_sync_id().unwrap();
63 assert_ne!(bridge.sync_id().unwrap(), Some("some_guid".to_string()));
65 assert_eq!(bridge.last_sync().unwrap(), 0);
67 bridge.set_uploaded(3, vec![]).unwrap();
69
70 bridge.reset().unwrap();
72 assert_eq!(bridge.last_sync().unwrap(), 0);
73 assert!(bridge.sync_id().unwrap().is_none());
74 }
75
76 #[test]
82 fn test_sync_via_bridge() {
83 ensure_initialized();
84 error_support::init_for_tests();
85
86 let store = Arc::new(LoginStore::new_in_memory());
87
88 insert_login(
91 &store.lock_db().unwrap(),
92 "local-only-aaaa",
93 Some("local-password"),
94 None,
95 );
96
97 let bridge = store
98 .clone()
99 .bridged_engine()
100 .expect("should create bridge");
101
102 bridge.sync_started().unwrap();
103
104 let incoming = vec![serde_json::json!({
107 "id": "remote-only-bbbb",
108 "modified": 0,
109 "payload": serde_json::json!({
110 "id": "remote-only-bbbb",
111 "hostname": "https://remote.example.com",
112 "formSubmitURL": "https://remote.example.com",
113 "username": "remote-user",
114 "password": "remote-password",
115 })
116 .to_string(),
117 })
118 .to_string()];
119 bridge
120 .store_incoming(incoming)
121 .expect("should store incoming");
122
123 let outgoing = bridge.apply(0).expect("should apply");
126 let changes: HashMap<String, serde_json::Value> = outgoing
127 .into_iter()
128 .map(|s| {
129 let bso: serde_json::Value = serde_json::from_str(&s).unwrap();
130 let payload: serde_json::Value =
131 serde_json::from_str(bso["payload"].as_str().unwrap()).unwrap();
132 (payload["id"].as_str().unwrap().to_string(), payload)
133 })
134 .collect();
135
136 assert_eq!(changes.len(), 1);
139 assert_eq!(changes["local-only-aaaa"]["password"], "local-password");
140
141 let stored = store
143 .get("remote-only-bbbb")
144 .unwrap()
145 .expect("remote login should have been stored");
146 assert_eq!(stored.password, "remote-password");
147
148 bridge
150 .set_uploaded(1234, vec!["local-only-aaaa".to_string()])
151 .unwrap();
152 bridge.sync_finished().unwrap();
153 assert_eq!(bridge.last_sync().unwrap(), 1234);
154 }
155}